あなたの最初の試みの問題:
find www/*.html -type f -exec sh -c "echo $(basename {})" \;
これは、コマンドが実行される$(basename {})
前に、コードが1回実行されることです。find
シングルの出力basename
は{}
、それが{}
ファイル名としてのベース名であるためです。したがって、findによって実行されるコマンドは次のとおりです。
sh -c "echo {}"
見つかったファイルごとに、実行される文字列に文字が表示されるfind
ため、実際には毎回元の(変更されていない)ファイル名に置き換えられます。{}
動作させたい場合は、二重引用符の代わりに一重引用符を使用できます。
find www/*.html -type f -exec sh -c 'echo $(basename {})' \;
ただし、とにかく標準出力に書き込んだecho
ものを標準出力に繰り返すことは、少し無意味です。basename
find www/*.html -type f -exec sh -c 'basename {}' \;
もちろん、それをさらに減らすことができます。
find www/*.html -type f -exec basename {} \;
ここで一重引用符と二重引用符の違いについても説明していただけますか?
これは通常のシェルの動作です。少し異なるコマンドを実行して(ただし、ファイルの名前はwww
1レベル下だけでなく、ディレクトリの下のどこにでも配置できます)、シングルクォート(SQ)バージョンとダブルクォート(DQ)バージョンを見てみましょう。指図:
find www -name '*.html' -type f -exec sh -c "echo $(basename {})" \; # DQ
find www -name '*.html' -type f -exec sh -c 'echo $(basename {})' \; # SQ
一重引用符は、囲まれた資料をコマンドに直接渡します。したがって、SQコマンドラインでは、起動するシェルがfind
囲んでいる引用符を削除し、find
コマンドはその$9
引数を次のように認識します。
echo $(basename {})
シェルが引用符を削除するためです。比較すると、二重引用符で囲まれた素材はシェルによって処理されます。したがって、DQコマンドラインでは、シェル(起動するシェルではfind
なく起動する find
)が$(basename {})
文字列の一部を確認して実行し、戻ってくるので、引数として{}
渡される文字列は次のようになります。find
$9
echo {}
さて、find
その-exec
アクションを実行すると、どちらの場合も、{}
(引数のために)見つけたばかりのファイル名に置き換えられますwww/pics/index.html
。したがって、2つの異なるコマンドが実行されます。
sh -c 'echo $(basename www/pics/index.html)' # SQ
sh -c "echo www/pics/index.html" # DQ
そこには(わずかな)表記上のチートがあります—これらはシェルで入力するのと同等のコマンドです。起動されたシェルの$2
は、どちらの場合も実際には引用符が含まれていません—起動されたシェルには引用符が表示されません。
ご覧のとおり、DQコマンドは単にファイル名をエコーします。SQコマンドは、basename
コマンドを実行してその出力をキャプチャし、キャプチャされた出力をエコーします。少し還元主義的な考え方は、DQコマンド-print
を使用する代わりにとして書く-exec
ことができ、SQコマンドをとして書くことができることを示してい-exec basename {} \;
ます。
GNUを使用している場合は、実行が不要になるようにフォーマットディレクティブが従うことができるアクションをfind
サポートします。ただし、これはGNUでのみ使用できます。ここでの残りの説明は、遭遇する可能性のあるすべてのバージョンに適用されます。-printf
basename
find
find