
我知道我可以使用通配符在 bash 中使用星號提取具有特定格式名稱的文件,如下所示:
$ ls
a01 a02 a03 a04 a05 a06 a07 a08 a09 b01 b02 b03 b04 b05 b06 b07 b08 b09
$ ls a*
a01 a02 a03 a04 a05 a06 a07 a08 a09
$ ls b*
b01 b02 b03 b04 b05 b06 b07 b08 b09
但是,如果我想做一些事情,例如將所有以 a 開頭的檔案移至名為 的目錄, a
並將所有以 b 開頭的檔案移至名為 的目錄b
,我該如何用一個命令來做到這一點?
你能做這樣的事情嗎:
$ mv *0* */
但不知何故引用了 move-to 參數中的第一個星號?
答案1
一條命令,一行:
for n in *;do [ -f "$n" ] && case "$n" in a*) mv "$n" a/;; b*) mv "$n" b/;; esac; done
或者,您可以從文件名中得出目錄的名稱,但我最初沒有顯示這一點,估計它是一個較長的行。例如,循環中的語句將是(第一次嘗試):
d=$(echo "$n" | sed -e 's/^\(.\).*/\1/'); [ -f "$n" ] && mv "$n" $d/
將使用給定檔案名稱的第一個字母來取得目錄名。與之比較
[ -f "$n" ] && case "$n" in a*) mv "$n" a/;; *b) mv "$n" b/;; esac
對於案例陳述。其實並不長,但更難即時打字。如bash
所提到的,可以使用其子字串語法${parameter:offset:length}
來縮短該行:
d=${n:0:1}; [ -f "$n" ] && mv "$n" $d/
或者
[ -f "$n" ] && mv "$n" ${n:0:1}/
(我記得這是一個 bash 擴展,並且在POSIX)。
關於重用通配符的實際問題:這顯然是指大括號擴展。這些在您需要它們之前就已展開。引用文件:
執行大括號擴展前任何其他擴展以及其他擴展所特有的任何字元都將保留在結果中。這是嚴格的文本。 Bash 確實不是將任何語法解釋應用於擴展的上下文或大括號之間的文字。為了避免與參數擴展發生衝突,字串“${”不被視為適合大括號擴展。