以下のようなコマンドをbashスクリプトで実行しようとしています。 $sourcedir
のすべてのサブフォルダーを検索し、特定のタイプのすべてのファイルを$targetdir
のルートレベルにコピーする必要があります。
#!/bin/bash
# These are set as arguments to the script, not hard-coded
sourcedir="/path/to/sourcedir"
targetdir="/path/to/targetdir"
find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2/`basename "$1"`"' "{}" "$targetdir" \;
{}
が$2
から-exec sh -c ...
として渡されていないことを除いて、これはかなり近いようです。
ファイル名の特殊文字(特に一重引用符)を許容して、これをできるだけ「正しい方法」に近づけたいと思います。
編集:xargs
または引数チェーンの使用を提案している人がいます。私はこれは限られた数の議論に対してのみ大丈夫だという印象を受けました。たとえば、いくつかのギャラリーディレクトリから巨大なスライドショーディレクトリにコピーしようとしている何千もの.jpgファイルがある場合でも、引数をつなぐソリューションは引き続き機能しますか?
編集2:私の問題は、_
コマンドでshを実行する最初のオプションの前に-exec
がないことでした。 findコマンドを機能させる方法に興味がある人は、_
を追加してください。すべてうまくいきます。
find "$sourcedir" -type f -name "*.type" -exec sh -c 'cp "$1" "$2"' _ "{}" "$targetdir" \;
ただし、同じタスクを実行しますが、より効率的でエレガントなので、以下の回答を受け入れました。
特定の種類のファイルを特定のディレクトリにコピーしますか?これはxargs
を使用するのが最適ですが、sh
は必要ありません。これはより適切な方法であり、より効率的に実行する必要があります。
find "$sourcedir" -type f -name "*.type" | xargs cp -t targetdir
特別なファイル名を処理する必要がある場合は、NULL
を区切り文字として使用してください
find "$sourcedir" -type f -name "*.type" -print0 | xargs -0 cp -t "$targetdir"
{}
を引数としてシェルに渡し、各引数をループする必要があります。
find "$sourcedir" -type f -name "*.type" -exec sh -c 'for f; do cp "$f" "$0"; done' "$targetdir" {} +
注:これが機能する方法は、シェルへの最初の引数がシェルの名前であることです。名前を$targetdir
として渡すことで、これを利用できます。次に、シェルスクリプト内で特別なパラメーター$0
を使用して、そのtargetdirにアクセスします。
Xargsの教会を信じないなら:
find "$sourcedir" -type f -name "*.mp3" -exec cp -t "$targetdir" {} +
説明:
cp -t a b c d
b、c、dをターゲットディレクトリaにコピーします。
-exec cmd {} +
大量のファイルに対して、一度にではなく、一度にコマンドを呼び出します(";"
の代わりに+
を使用する場合、これは標準です)。これが、targetdirを手前に引き、明示的にターゲットとしてマークする必要がある理由です。
これはgnu-findで機能し、findの他の実装では機能しない場合があります。もちろん、それは-t-フラグにも依存しています。
もちろん、TechZillaはこれまでのところ、cpを呼び出すためにsh
は必要ありません。
xargs
を使用しない場合は、ほとんどの場合find
と組み合わせて不必要ですが、-print0
フラグと-0
フラグを学習する必要はありません。
read -p "SOURCE: " sourcedir
read -p "TYPE: " type
read -p "TARGET: " targetdir
find -L $sourcedir -iname "*.$type" -exec cp -v {} $targetdir \;