
我想使用 find 查找某些文件,然後使用 xargs 與 cp 和 sed 將這些文件移動到另一個資料夾並重命名。我知道如何循環執行此操作,但這不是我想要的。
我試過:
find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')
為什麼這不起作用以及解決方案是什麼?
答案1
嘗試這個。它不需要xargs
,只需find
和。它不會更改任何文件,但是sed
copy
將要列印用於複製檔案的 shell 命令清單。因此,如果您喜歡它列印的命令,那麼您可以再次運行它並刪除最後一行#
之前的內容sh -x
,然後讓 shell 執行命令。
find "${FOLDER:-.}" -iname "*${SOME_STRING:-ABC}*" |
sed "
s/^/'/ # surround filename with single quotes
s/$/'/
h # save filename in the sed hold space
s/ABC/XYZ/g # change filename
H # append to hold space (separates with newline)
g # get original and modified from hold
s/\n/ /g # replace the newline with a space
s/^/cp -i/ # make it into a copy command
" #| sh -x # optionally pipe to shell
xargs
為什麼這種方法比本例更好?因為除了每個檔案所需的命令之外,此方法總共只啟動 3 個進程(find
、sed
和)。sh
cp
要使用xargs
,處理每個檔案名稱將需要比單一所需cp
命令更多的進程。
讓 sed 的一次調用產生的效率高得多全部命令cp
,而不是為每個檔案名稱呼叫一個新sed
進程。
答案2
使用 GNU Parallel 看起來像這樣:
find ${FOLDER} -iname "*${SOME_STRING}*" |
parallel cp {} '{= s/ABC/XYZ/g =}'
{= =} 建構包含更改 $_ 的 Perl 表達式。
優點之一是 GNU Parallel 會做正確的事情,即使您有名為:
My brother's 12" records worth >100$.txt
或類似的恐怖:
touch Y-"$(perl -e 'print pack("c*",1..9,11..46,48..255)')"