Findでこれらのコマンドをどのように実行できますか?

Findでこれらのコマンドをどのように実行できますか?

FreeBSDを使用していますが、文字列の一部として{}を含むコマンドを実行できません。たとえば、見つかったファイルの名前を変更する場合です。これは状況の例です。質問自体は、「{}」構文の一般的な問題を解決することです。

find . -type f -name 'data*' -execdir mv {} OLD_{} \;
find . -type f -name 'data*' -execdir mv {} archive/{} \;

-execdirインクルードディレクトリ内でコマンドを実行して{}ファイル名のみを拡張すると、インクルードディレクトリパスに関する問題を回避できます。

2つの質問があります。

  1. -execdir mv節でパラメータを適切に引用する方法(多くのファイルの名前にはスペースまたは一重引用符があります)。
  2. ファイル名を完全に変更するようにターゲットを取得するにはどうすればよいですか?

2番目の問題は、{}「見つかったエントリのパス」が先行/末尾のスペースで囲まれている場合にのみ拡張されるように見えるため、コマンドパラメータがめちゃくちゃになるために発生します。空白以外の先行文字と末尾文字の例:

# /usr/bin/find . -maxdepth 1 -execdir echo "(result):" {}  \;
(result): .
(result): dir 1
(result): dir 2
(result): dir 3

# /usr/bin/find . -maxdepth 1 -execdir echo "(result):"{}  \;
(result):
(result):
(result):
(result):

# /usr/bin/find . -maxdepth 1 -execdir echo {}":(result)" \;
:(result)
:(result)
:(result)
:(result)

man find指摘-execおよび-ok rudimentaryの歴史的実装は、ユーティリティ名またはユーティリティ引数の前または後に空白以外の文字がある場合は文字列 "{}"を置き換えませんでした。ユーティリティ名のどこにあっても、このバージョンはを実行します。交換しないと、引数が表示されます。が、そんなことは起こらないようです。

実行したいコマンドをどのように実行しますか?

ベストアンサー1

この動作は、シェルとして使用するとfindFreeBSD 11.1-RELEASEでは再現できません。/bin/sh以前は/bin/cshしかし、両方とも再現できました/bin/tcsh

cshとでこの問題を解決するには、を引用するか、tcsh次の方法を使用します。{}\{\}'{}'


文字列の一部として使用されたときにfind正しく拡張されない実装では、現在のパス名を他の文字列と正しく関連付けるには、サブシェルを使用して実行できます。{}

例:

find . -type f -name '*.c' -exec sh -c 'printf "(result):%s\n" "$@"' sh {} +

またはecho(ただし、「参照」)なぜprintfがechoより優れているのですか?"),

find . -type f -name '*.c' -exec sh -c '
    for name do
        echo "(result):$name"
    done' sh {} +

または

find . -type f -name '*.c' -execdir sh -c '
    for name do
        mv -- "$name" "OLD_${name##*/}"
    done' sh {} +

つまり、sh -cコマンドライン引数としてサブシェル(ここ)のパス名を指定し、通常はシェル変数を使用するのと同じように、結果シェルでそのパス名を使用して接続します。

${name##*/}上記は、GNUがパス名を使用するときにパス名の前に追加するのを防ぐためですfind)。./-execdir

関連:

おすすめ記事