使用 find 指令加入到檔案名稱前面

使用 find 指令加入到檔案名稱前面

有沒有辦法僅使用 find 指令在檔案名稱前面添加一個字串?

這樣:

201a.txt
201b.png
...

就變成這樣了:

foo_201a.txt
foo_201b.png
...

這:

find . -name '201*' -execdir mv {} foo_{} \;

不起作用,因為該{}部分包含文件名中的前導./,因此嘗試寫入foo_./201*.

如果僅使用 find 無法做到這一點,那麼將字串新增至檔案名稱的最可移植(閱讀:僅 coreutils,沒有 shell 腳本,最容易理解)的方法是什麼?

答案1

rename不。

$ ls -1
201a.txt
201b.png
$ rename 201 foo_201 201*
$ ls -1
foo_201a.txt
foo_201b.png
$

答案2

怎麼樣

find . -name '201*' -execdir basename {} \; | xargs -I{} mv {} foo_{}

basename是由提供的coreutils,並且由於xargs是由提供的,因此findutils它應該至少與find -execdir它本身一樣可移植。


或者,僅使用 POSIX shell 功能

find . -name '201*' -execdir sh -c 'mv "$1" "foo_${1#*/}"' sh {} \;

答案3

單獨使用這是不可能的find,即使使用 GNU find 也是不可能的。 GNU find 可以列印刪除命令列前綴並添加另一個前綴的文件,方法是使用-printf foo_%p代替-print,但是 沒有任何類似的東西-exec

find -printf 'mv foo_%p …' | sh如果你喜歡危險地生活,你可以使用 , 。這只適用於“馴服”的文件名,如果文件名中有空格、引號和其他特殊字符,它會嚴重中斷。所以不要這樣做。)

執行此操作的標準方法(就像在任何 POSIX 系統上工作的方式一樣,也是一種常見的方式)是呼叫 shell 來執行字串操作。

find . -name '201*' -exec sh -c 'mv -- "$0" "${0%/*}/foo_${0##*/}"' {} \;

我不使用它,-execdir因為它是一個 GNU 擴展,而你要求可移植性。請注意,它{}作為參數傳遞給 shell。切勿在 shell 程式碼內部使用{}:不僅因為它不可移植,而且最重要的是因為它會導致檔案名稱被解釋為 shell 程式碼,如果檔案名稱包含特殊字符,則會失敗。

在現代 POSIX 系統(過去十年的任何系統)上,您可以透過批次 shell 呼叫來稍微加快此命令的速度。

find . -name '201*' -exec sh -c 'for x do mv -- "$x" "${x%/*}/foo_${x##*/}"; done' sh {} +

或者,在 ksh、bash 或 zsh 中,您可以使用遞歸通配符而不是呼叫find.

set -o globstar # ksh only
shopt -s globstar # bash only
for x in **/201*; do
  mv -- "$x" "${x%/*}/foo_${x##*/}"
done

答案4

您可以使用星號 ( *) 來代替,它會刪除該./部分:

find * -name '201*' -exec mv {} foo_{} \;  

相關內容