xargsの引数を使用して他の式を評価する方法は?

xargsの引数を使用して他の式を評価する方法は?

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)評価されます(文字列の生成)。これがコードがファイルを正しい名前にコピーしない理由です。fxargs

「該当するファイルまたはディレクトリがありません」というエラーは、見つかったファイルのパス名に置き換えられたためにf発生します。DIR_OUT/copied_ffind


同じことを行うより強力な方法

find . -type f -name '*.txt' -exec sh -c '
    for pathname do
        cp "$pathname" "DIR_OUT/copied_${pathname##*/}"
    done' sh {} +

または、見つかったパス名を間にNULLで終わる文字列として渡すようにxargs注意してください。findxargs

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 ffindがファイルの結果のみを提供することを確認する -print0make findはnull終了出力を出力します。 1つの結果のみがプロセスに渡されるよう -n1にします。結果がない場合は、ジョブを実行しないように指示します。 make find は null 終了入力を受け入れます。xargs-rxargs-0xargs

runコマンドは、インラインスクリプトと空の引数を持つシェルです(-c引数がスクリプトに渡される方法であるため)。

xargs引数を に渡すと、sh -c 'commands' ''最初の引数が$1-c 内になります。一重引用符はシェル処理の呼び出しを防ぎ$()ます$1

関連情報