findコマンドの正規表現 - 変なファイルが出来てしまったときどうやって消しますか?
nkfのソースの文字化けを直して読もうと,ついこんなコマンドを...
$ nkf nkf.c | vi -R
その結果,
$ ls 00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 (snip) 00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a, 00,0x00}; 00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00, 0201_f = ((!iso2022jp_f)? TRUE : NO_X0201); 21,0x21,0x21,0x23,0x21,0x56,0x21,0x57, 21,0x22,0x21,0x26,0x25,0x72,0x25,0x21, (snip) 25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c, 3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00, 5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27, 5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00, 7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00, INSTALL INSTALL.j MANIFEST Makefile (snip) utf8tbl.h version.rc
変な名前のファイルが...
こんなとき,これらのファイルをどうやって消しますか?
私は今回findとxargsを使いました.
ファイル名の傾向からいって正規表現使うのがいいだろうと考えました.
$ find . -maxdepth 1 -regex '..[0-9]\([b-e]\|[0-9]\).*' -exec rm -i {} \;
で消せるようです.
man findには
-regex pattern ファイル名が正規表現 pattern にマッチすれば真。このマッチは ( す べてのパスを含む) ファイル名全体に対してでなければならない。例え ば ‘./fubar3’ というファイルにマッチさせ る に は 、 正 規 表 現 ‘.*bar.’ や ‘.*b.*3’ が使えるが、 ‘b.*r3’ はマッチしない。
こんなことが書いてあるので,部分マッチを使った'[0-9]\([b-e]\|[0-9]\)'ではダメみたいです.
それと,findでの選択とグループ化には,シングルクォーテーションを使ってもバックスラッシュが必要なようです*1.
grep*2と同じですね.egrepでは必要ないです.
xargsでは.ファイル名が似ていて順に並んでいるのを利用して
$ ls | head -n 40 | xargs -i rm {}
としました.
個人的には前者の方を使っていきたいと思います.
余計な話
xargsを使った例での怖い(と私が感じる)ところは,lsで表示されるファイルには"./"がついていないため,
端末の一行に表示されたファイルが,単一ファイルなのか長いファイル名を折り返されているのか分からないところかもしれません.
それでもheadを使っているので,ファイル数と行数を一致させることができるとは思いますが.
ファイル名が短い場合だと,私は普段
$ ls | sed 's/\ /\n/g' | headとかtailとか
と抽出しています.
lsの仕様がどうなっているのか分からないので,
今回のようにファイル名が長い場合に,ファイル名の区切りが改行になっていることは分かりませんでした.
ゆえに安全のためにはfindのように"./"がついている方が安心できます.
また,xargsを使った場合rmのiオプション指定の仕方が分かりませんでした.
$ ls | head -n 40 | xargs -i rm -i {}
としてしまうとユーザの確認が無視して,次のファイルの処理に移ってしまいます.
確認されていないのでファイルは消えませんが.
例えば,”ls -l”は使えました.
オプションiがxargsのオプションと重複しているためとも考えましたが,
”grep -i”も使うことができました.
たぶん,先に述べたようにユーザからの入力を待たないだけの話なんでしょうね.
lsとheadで抽出したファイルが正しいなら確認は無くてもよいのですが,一応.