find の -prune の使い方
find で特定ディレクトリだけ除外するために -prune を使うとたまに思い通りにいかないので調べてみた。要するに暗黙に付けられる -print によって挙動が変わる。
find . -name ".git" -prune -o -type f -print の擬似コード
find(dir) { for name in dir { FollowSubDirectory = true; if (name == ".git") // -name ".git" { FollowSubDirectory = false; // -prune } else // -o { if (type(name) == FILE) // -type f { print name; // -print } } if (type(name) == DIRECTORY && FollowSubDirectory == true) { find(dir); } } }
find . -name ".git" -prune -o -type f の疑似コード
find(dir) { for name in dir { FollowSubDirectory = true; if (name == ".git") // -name ".git" { FollowSubDirectory = false; // -prune print name; // ★ } else // -o { if (type(name) == FILE) // -type f { print name; // ★ } } if (type(name) == DIRECTORY && FollowSubDirectory == true) { find(dir); } } }
まとめ
アクションを一つも指定していない場合は、各条件成立時に print が指定されているものとして取り扱われる (man 参照)。これは、
アクションを指定しているときと、していないとききで find は挙動が違う場合がある
ことを意味し、
-exec で実行する前に、-exec なしで find を実行して対象を確認していたがこれは -exec が付いた場合の対象とは異なる場合がある。-print を明示的に付けるか、-exec echo '{}' などとしてきちんと評価した方がよい