
回答のまとめ: 文献では、「-execdir」が「-exec」よりも安全であると宣伝していますが、動作上の違いを無視しないでください。前者は後者の単純な再実装ではない。また、インタラクティブな削除に特別にfindを使用している場合は、「-okdir」オプションを指定して「rm -f」を実行することもできます。やや複雑な構造の場合も同様です。
「find」コマンドを学習しようとしていますが、その出力を理解できません。これが重複した場合はお詫び申し上げます。しかし、問題の説明は少し複雑でグーグルが難しいです。
ペットボックスを設定します。いくつかのディレクトリ(「.」)から始まり、「A」と「B」という2つのサブディレクトリがあります。どちらのファイルにも「hello.c」というファイルがあります。
例えば、
find . -name "hello.c"
次のように印刷されます。
./A/hello.c
./B/hello.c
今まではそんなに良くなった。 "-execdir"オプションを使用しようとすると迷子になります。インタラクティブな削除を使用したいとしましょう。それから:
find . -name "hello.c" -execdir rm -i {} \;
または同様です。私が期待したのは
rm: remove regular file "./A/hello.c"?
その後、この質問に答えるために、同様の "hello.c"プロンプトが "B"ディレクトリに表示されます。残念ながら、実際に起こっていることは
rm: remove regular file "./hello.c"?
この小さな例では、「./A/hello.c」を要求していると合理的に推論できますが、この例を拡張すると、パス名が「./」で切り捨てられた数十のファイルが得られます。何十もの "./hello.c"がそれぞれどのサブディレクトリにあるかを区別することはできません。
だから私の質問は、「-execdir」を介してより完全なパス名を印刷したいということです。マンページで私が認識していないいくつかの微妙なことについてのヒントを聞くことはできますか? 「{}」の交換にはほとんど知られていません。あるいは、この特定のケースを管理するためのより良い方法(対話型削除)がある場合は、私のアプローチがベストプラクティスであるかどうかわからないので、聞きたいです。
答え1
GNUのマニュアルページではfind
これについて部分的に説明します。-execdir
に似ています
-exec
が、指定されたコマンドは通常、起動したディレクトリではなく一致するファイルを含むサブディレクトリで実行されますfind
。
したがって、実際の微妙さは含まれません。-exec
コマンドが実行されているディレクトリからコマンドを呼び出しfind
(したがって、そのディレクトリへの相対パスまたはルートの絶対パスを指定する必要があります)、ファイルを-execdir
含むディレクトリからコマンドを呼び出すため、提供する必要はありません。フルパスパスなのでそうではありません。
必要な動作を得るには代わりに-exec
使用する必要があります-execdir
。
rm
呼び出しをecho
単に引数リスト(この場合はファイル名)印刷に置き換えることで、この動作を表示できます。または、-print
外部コマンドを呼び出さずにこれを実行するには、whichを使用します。 (注:-print
指定されていない場合、これはデフォルトのタスクでもあります。)
確認が不要な場合に-delete
機能します。これはrm
繰り返し呼び出すのを防ぎ、大量のファイルに対してより効率的になる可能性があります。
答え2
セキュリティ上の利点を得て-execdir
(実際には、コマンドが複数のコンポーネントを含むパスを取得しないようにするため)、プロンプトを取得するには、次のようにします。
find . -name hello.c -okdir rm -f {} \;
(少なくともGNUの実装は、GNUのようにfind
端末に適した方法rm
(wrtコントロール、改行、印刷できない文字...)でファイル名をエスケープしないことに注意してください。)
答え3
-exec
よりシンプルで安全性の低いディレクトリを使用する代わりに、作業ディレクトリを印刷できます。例えば
-execdir sh -c 'pwd ; rm -i "$1"' . {} \;
または、フルパスを印刷します。
-execdir sh -c 'readlink -e "$1" ; rm -i "$1"' . {} \;