Mac が勝手に複製した "hoge 2.txt" 的なファイルを一括削除する


"hoge 2.txt"、それは突然現れた

僕、Github の private リポジトリに高専時代・大学時代の歴史をバックアップしてるんですけど、そのローカルファイルを iCloud Drive にも保存してたんですね。
今日ファイルの中身が見たくなって雲のマーク「ぽちー」って押して、ローカルに落としたんです。

一通り閲覧して満足したので、一応変な diff が無いか確認するために git status を叩きました。

すると「ズラズラズラーーーーーーー」っと無数にアウトプットが。。。。
しかも全部 unstaged files なんですよ。

「怖いなー、怖いなー。何も追加してないのになー。」
って思ってよく見ると、全部「hogehoge 2.pdf」みたいに、 "2" っていうのが拡張子の直前に付いてたんです。。。

それはなんと、全部 Mac が勝手に複製したファイルだったんです。。。。

対処法

はい。ということで、真面目に対処法をシェアします。
症状としては勝手にファイルが複製されて、全部拡張子の直前に 2 が付いている状態です。
例: hoge.txt の複製ファイルとして hoge 2.txt が作られている。

今回はこの、 2 とついたファイルだけを削除するワンライナーを紹介します。
結論から言うと、

$ find . -maxdepth 10 -type f | grep " 2\.*"| sed -e 's/ /\\ /g' | xargs rm

というコマンドを叩けばいいです。
お疲れ様でした。

。。。で終わるのもなんか味気ないので、軽く解説します。

解説

ワンライナーをもう一度。

$ find . -maxdepth 10 -type f | grep " 2\.*"| sed -e 's/ /\\ /g' | xargs rm

これをパイプ毎に分けると、

  1. 深さを指定して列挙: find . -maxdepth 10 -type f
  2. 2. と付くファイルのみに絞り込み: grep " 2\.*"
  3. スペースをエスケープ: sed -e 's/ /\\ /g'
  4. 削除: xargs rm

一つづつ解説します。

1. 深さを指定して列挙: find . -maxdepth 10 -type f

これは特に問題ないかと思います。
今回は下階層全て検索したかったので、 -maxdepth 10 を付けて 10 階層下まで見に行くようにしています。

find .find ${path/to/directory} とすれば好きなディレクトリについて検索できます。

2. 2. と付くファイルのみに絞り込み: grep " 2\.*"

ここも特筆することはないです。

. はそのままだとエスケープが必要なので、バックスラッシュを付けて \. としています。
これで ${半角スペース}2. をファイル名に含むものだけ抽出できます。

3. スペースをエスケープ: sed -e 's/ /\\ /g'

これがこのワンライナーの肝だと思います。
何をしているかと言うと、半角スペースにバックスラッシュを付けてエスケープさせています。
理由としては、このまま rm コマンドに渡してしまうと、半角スペースで区切られて別ファイルとして扱われてしまうためです。


例: hoge 2.txt というファイルを削除する場合

  1. rm hoge 2.txt を実行してみる
  2. rm コマンドの気持ちとしては hoge2.txt というファイルが渡されたと勘違い
  3. 「そんなファイルは無いよ」と言われるか運悪く hoge または 2.txt ファイルが意図せず削除されてしまう

なんかスラッシュばっかりで分かりにくいとは思いますが、置換コマンドは

$ sed -e 's/${置換前}/${置換後}/g'

でその行に含まれた全ての対象を置換してくれます。
このコマンドとの diff を取れば、

  • 置換前テキスト: ${半角スペース}
  • 置換後テキスト: \\${半角スペース}

というように指定していることが分かると思います。
さらに、バックスラッシュが連続しているのは、バックスラッシュそのものをエスケープするためで、実質 1 つのバックスラッシュを付けています。
つまり、半角スペースの前にバックスラッシュを付けているのです。

これにより、 rm コマンドが勘違いせずやってくれるはずです。

4. 削除: xargs rm

なんてことはないですが、最後に絞り込まれ、半角スペースをエスケープしたファイル名が指定され、削除される。

という全体的な流れです。

参考