正規表現やワイルドカードでファイル名を一括変換する

2017/03/14

複数のファイルの名前をあるルールで一括して変換する方法。
(動作確認 RedHat6.2)

xargsfor + sedxargs + sedの順にシェルでの実現方法を書いていき、複雑度が増す場合にRubyでシンプルに実現する方法も書く。

RedHat系はrenameは不向き

簡単なルールであればrenameコマンドを使用すればいい。

しかし正規表現を使用しなければいけないようなルール、たとえば末尾に.csvをつけるといったようなことはできない。
ネットではsedのように 's/regex/regex/' 形式で指定できると書いてあったが、RedHat6.2に入っているrenameコマンドは対応していなかった。
Linuxには2つのrenameコマンドが存在し、正規表現が使えるのはperlで作られたDebian系のrenameの方であり、RedHat系はutil-linuxに含まれるrenameコマンドなので、複雑なルールには不向き。

find + xargs

findやlsの結果をxargsで受けて、一つずつ処理するのが汎用的に使える。

【要件】test_で始まる複数のファイル名の末尾に.csvをつける。
【方法】

【説明】find -printf '%f\n'でtest_で始まるファイルのファイル名部分だけを抜き出し、ファイル名を一つずつmvする。

さらにfor文とsedを合わせて柔軟な正規表現変換

for文とsedを合わせて使うと、今回のように末尾に文字を付けたり外したりするだけでなく、より柔軟な変換が可能になる。

【要件】_ を . に置き換えてファイル名を変換する。
【方法】

for文を使わずsedだけでワンライナー実行

上で正規表現で柔軟に変換するにはfor文を合わせて使うと書いたが、sedだけでワンライナー実行もできる。※ただし少し複雑になる。

【要件】_ を . に置き換えてファイル名を変換する。
【方法】コマンドを分解して説明する。

結論としては、次のコマンドになる。

※sedの拡張正規表現-r-Eの場合も。今回の例だと拡張でなくてもいいので-eでも可。
※sedの偶数行を取得する2~2s/_/./gn;s/_/./gでも可。

オプション 説明
n N 入力の次の行をパターンスペースに読み込む/追加する。
addr1,~N addr1 から、addr1 以降の、入力行番号が N の倍数の行までマッチする。
addr1,+N (参考) addr1 から、addr1 以降の N 行にマッチする。

シェルスクリプトではなくRubyで置換とrenameを行う

for文とsedを合わせて柔軟な正規表現変換を行うまでは十分に読みやすいシェルコマンドだったが、ワンライナーで実現しようとすると途端に複雑になってしまった。ワンライナーでも簡単な記述で実現するためにRubyを使う。
lsの結果をRubyに渡して置換とrenameを行う方法と、rename対象を選別するところから全てRubyで行う方法の二通りで書いてみる。

まずはlsの結果を渡す方法を過程も含めて詳しく見ていく。

File#renameを使用してもいいがFileUtils#mvも使える。

次にrename対象を選別するところから全てRubyで行う方法も書いてみる。

Rubyプログラムとしてはこちらの方が正統なのだろうが、ワンライナーとしてははじめの方が好み。

最後にRubyワンライナーのまとめとして3つの方法を再掲する。

-Linux, Ruby
-, , , ,