Find

如何即時復製文件列表並調整目標文件名?

  • February 25, 2013

當我不需要調整目標文件名時,我可以這樣做:

$ find -type f -name '*.pat' -print0  | xargs -O cp -t /path/to/dest

這是安全的,因為文件名甚至可能包含換行符。

替代:

$ find -type f -name '*.pat' -print0 | cpio -p -0 -d /path/to/dest

現在我的問題是目標是 VFAT 文件系統……因此文件名中不允許使用某些字元(例如“?”)。這意味著我必須調整目標文件名。

就像是

for i `find -type f -name '*.pat'` ; do
   cp "$i" `echo $i | sed 's/?/_/'`
done

僅適用於沒有空格的文件名 - 我可以將 IFS 更改為換行符 - 但是如何將 ‘\0’ 設置為 IFS?

而且 - for 循環會導致與文件一樣多的 forks/exec(mv/sed) - 這比開始的兩個範例所需的少數 forks/exec 多得多。

解決該問題的替代方法是什麼?

pax至少可以在 Debian、Suse、OpenBSD、NetBSD 上找到:

find . -type f -name '*.pat' -print0 | pax -0rws'/?/_/gp' /path/to/dest/

pax是一個標準實用程序(與taror相反cpio),但它的-0選項不是,儘管可以在一些實現中找到。

如果同時存在 a?.pat_.pat文件,它們最終將被替換為相同的名稱,因此其中一個將覆蓋目標中的另一個。同樣,如果有一個_and?目錄,它們的內容將合併到_目標目錄中。

使用 GNUsort和 GNU uniq,您可以預先檢查衝突:

find . -type f -name '*.pat' -print0 |
 tr '?' _ |
 sort -z |
 uniq -zd |
 tr '\0' '\n'

這將報告衝突的文件(但不是目錄)。

您可以使用zsh’szmv來解決衝突,但這仍然意味著每個文件一個mkdir和一個:cp

autoload zmv
mkdir-and-cp() {mkdir -p -- $3:h && cp $@}
zmv -n -Qp mkdir-and-cp '(**/)*.pat(D.)' '/path/to/dest/$f:gs/?/_/'

-n(高興時刪除)。

引用自:https://unix.stackexchange.com/questions/65926