
find を使用して特定のファイルを検索し、xargs と cp および sed を使用してこれらのファイルを別のフォルダーに移動して名前を変更したいと考えています。これをループで実行する方法はわかっていますが、それは私が探しているものではありません。
私は試した:
find ${FOLDER} -iname "*${SOME_STRING}*" | xargs -I {} cp {} $(echo {} | sed 's/ABC/XYZ/g')
なぜこれが機能しないのでしょうか、そして解決策は何でしょうか?
答え1
これを試してみてください。 は必要ありませんxargs
。 と だけfind
ですsed
。copy
ファイルは変更されませんが、意思ファイルをコピーするためのシェル コマンドのリストを出力します。出力されるコマンドが気に入ったら、再度実行して最後の行の#
の前のを削除しsh -x
、シェルにコマンドを実行させます。
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を1回呼び出すだけで、全て各ファイル名ごとにcp
新しいプロセスを呼び出すよりも、コマンドのほうが簡単です。sed
答え2
GNU Parallel を使用すると次のようになります。
find ${FOLDER} -iname "*${SOME_STRING}*" |
parallel cp {} '{= s/ABC/XYZ/g =}'
{= =} 構造には、$_ を変更する Perl 式が含まれています。
利点の 1 つは、次のようなファイルがある場合でも、GNU Parallel が適切に動作することです。
My brother's 12" records worth >100$.txt
あるいは次のような恐ろしいこと:
touch Y-"$(perl -e 'print pack("c*",1..9,11..46,48..255)')"