workspace以下の通常ファイルのうち、名前が.tmpで終わるものをarchiveへ移動する。
workspace/subも検索対象とし、2つの.tmpファイル名は互いに異なるものとする。
workspace/
├── a.tmp
├── keep.txt
└── sub/
└── b.tmp
archive/適切なコマンドはどれか。
findは指定した起点以下を再帰的に検索します。-type fと-nameで対象を絞り、-execの{} +で複数パスをまとめてmvへ渡せます。
詳細解説
mv workspace/*.tmp archive/通常の*はディレクトリ区切りをまたがないため、sub/b.tmpは対象外です。
誤りです。*は通常、スラッシュをまたいで一致しません。workspace直下のa.tmpは移動できますが、workspace/sub/b.tmpは対象外です。
globstarを有効にした**など別の仕組みもありますが、このコマンドには再帰指定がありません。
find workspace -type f -name '*.tmp' -exec mv -t archive -- {} +再帰的に通常ファイルを探し、該当パスをまとめてmvへ渡します。
正しい選択肢です。find workspaceでworkspace以下を再帰探索し、-type fで通常ファイル、-name '*.tmp'で名前を絞ります。
-execの{}は見つかったパスに置き換わり、末尾の+は複数パスを可能な範囲でまとめて1回のmvへ渡します。--は、先頭がハイフンのファイル名をオプションと誤認しないための区切りです。
find workspace -type d -name '*.tmp' -exec mv -t archive -- {} +-type dはディレクトリだけを対象にします。今回は-type fが必要です。
誤りです。-type dはディレクトリだけを対象にします。今回移動したいa.tmpとb.tmpは通常ファイルなので、-type fが必要です。
名前が.tmpで終わっていても、オブジェクト種別が条件と違えばfindの結果には入りません。
find workspace -type f -name '*.tmp' -delete条件に合うファイルを移動せず削除します。目的と異なる破壊的操作です。
誤りです。検索条件は一致しますが、-deleteは対象ファイルを削除します。archiveへ移動する要件を満たさず、復元が難しい破壊的操作です。
findのアクションを確認するときは、先に-printで対象を表示し、意図した集合であることを確認してから変更操作へ進むと安全です。
実際に確かめる
一時的な検証環境で実行できる例です。
mkdir -p workspace/sub archive
touch workspace/a.tmp workspace/keep.txt workspace/sub/b.tmp
find workspace -type f -name '*.tmp' \
-exec mv -t archive -- {} +
find . -maxdepth 3 -type f -printf '%P\n' | sort期待される結果
archive/a.tmp
archive/b.tmp
workspace/keep.txt理解のポイント
- globとfindの検索範囲の違い
- -type fと-nameによる絞り込み
- 本番では同名ファイル衝突も別途設計する
確認時の注意
- 確認環境:
- 変更前に-exec部分を-printへ置き換えると対象だけを安全に確認できます。
- 検証用ディレクトリで実行し、既存のworkspaceやarchiveを上書きしないでください。
基礎のおさらい
globとfind
globはシェルがコマンド実行前に展開します。findはコマンド自身が指定した起点以下を探索します。検索範囲と展開主体が異なります。
クォートする理由
'*.tmp'をクォートしないと、findへ渡る前に現在のシェルが展開する可能性があります。パターンをfind自身に解釈させるためクォートします。
{} +と{} \;
{} +は複数パスをまとめて実行し、{} \;は1パスごとに実行します。大量ファイルでは{} +の方がプロセス起動回数を抑えられます。
同名ファイルの衝突
異なるディレクトリの同名ファイルを1つのarchiveへ集めると衝突します。本番処理では上書き方針やディレクトリ構造の保持を別途決めます。