ファイルリストをコピーし、ターゲットファイル名を即座に調整するには?

ファイルリストをコピーし、ターゲットファイル名を即座に調整するには?

ターゲットファイル名を調整する必要がない場合は、次のことができます。

$ 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 ループはファイル (mv/sed) と同じくらい多くのフォーク/exec を発生させます。これは、最初の2つの例で必要とされるいくつかのフォーク/execよりもはるかに多いです。

この問題を解決するための代替案は何ですか?

ベストアンサー1

pax少なくともDebian、Suse、OpenBSD、NetBSDで見つかります。

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

pax標準ユーティリティ(同じtarまたは逆cpio)、-0いくつかの実装で見つけることができますが、そのオプションはそうではありません。

?.patファイルとファイルの両方が_.pat存在する場合は、同じ名前に置き換えられるため、ターゲット上の1つが別のファイルを上書きします。同様に_、ディレクトリがある場合、その内容はターゲットディレクトリ?にマージされます。_

GNUsortとGNUを使用すると、uniq競合を事前に確認できます。

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

競合するファイルを報告します(ディレクトリを除く)。

zsh'を使用してzmv競合を解決することはできますが、これはまだファイルごとにmkdir1プラス1を意味します。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)。

おすすめ記事