basename
引数が与えられた式を評価したいと思いますxargs
。
私がテストしたものは次のとおりです。
find . -name '*.txt' | xargs -I f cp f DIR_OUT/copied_$(basename f)
きちんと評価されなかったno file or directory
からだ。$(basename f)
ファイル名をコピーして変更する2つのステップに分けられますが、xargs
。
答え1
コマンドで使用されるコマンド置換は、コマンドが開始される前に一度だけ$(basename f)
評価されます(文字列の生成)。これがコードがファイルを正しい名前にコピーしない理由です。f
xargs
「該当するファイルまたはディレクトリがありません」というエラーは、見つかったファイルのパス名に置き換えられたためにf
発生します。DIR_OUT/copied_f
find
同じことを行うより強力な方法
find . -type f -name '*.txt' -exec sh -c '
for pathname do
cp "$pathname" "DIR_OUT/copied_${pathname##*/}"
done' sh {} +
または、見つかったパス名を間にNULLで終わる文字列として渡すようにxargs
注意してください。find
xargs
find . -type f -name '*.txt' -print0 |
xargs -0 sh -c '
for pathname do
cp "$pathname" "DIR_OUT/copied_${pathname##*/}"
done' sh
両方のバリエーションで、指定されたパス名を繰り返し、それをディレクトリの下の新しい名前にコピーする小さなインラインシェルスクリプトを呼び出しますDIR_OUT
。${pathname##*/}
に置き換えることができます$( basename "$pathname" )
。
-print0
(in find
)と-0
(in)はxargs
非標準ですが、一般的に実装されています。
関連:
答え2
元のコマンドを少し変更する必要があります。
find . -name '*.txt' | xargs -I f sh -c 'cp f DIR_OUT/copied_$(basename f)'
答え3
説明するには、$()
シェルで実行する必要がありますxargs
。
バラよりここ
また、ファイル名に問題のある文字が表示されないようにするには、システムで許可されている場合は find の null で区切られた出力を使用する必要があります。
これにより、目的のタスクが実行されます。 (どこかにnullサポートがない場合は、-0
から削除してxargs
に-print0
置き換えてください-print
。)
find . -type f -name '*.txt' -print0 | xargs -n1 -r0 /bin/sh -c 'cp "$1" "DIR_OUT/copied_$(basename "$1")"' ''
-type f
findがファイルの結果のみを提供することを確認する
-print0
make findはnull終了出力を出力します。 1つの結果のみがプロセスに渡されるよう
-n1
にします。結果がない場合は、ジョブを実行しないように指示します。 make find は null 終了入力を受け入れます。xargs
-r
xargs
-0
xargs
runコマンドは、インラインスクリプトと空の引数を持つシェルです(-c
引数がスクリプトに渡される方法であるため)。
xargs
引数を に渡すと、sh -c 'commands' ''
最初の引数が$1
-c 内になります。一重引用符はシェル処理の呼び出しを防ぎ$()
ます$1
。