renameコマンドを使えない環境でファイル名を一括変更

renameコマンドが使えれば簡単にファイル名を一括変更できるのですが、macOSのように利用できない環境も多々あります。そのような環境でファイル名を一括変換する方法です。

1.find, sed, xargsで変更する方法

コマンドのテンプレートはこうなります。

find <検索対象ディレクトリパス> -type f | sed 'p;s/<置換条件>/<置換文字列>/' | xargs -n2 mv

まず、findコマンドで検索対象ディレクトリからファイルのみを検索します。実行結果はこうなります。

find ./ -type f
.//aaaa001.txt
.//aaaa002.txt
.//aaaa003.txt

次にsedコマンドでfindコマンドの結果を検索置換します。これはfindコマンドで検索した結果の文字列を検索置換し、その結果を出力するだけで、実際にファイル名が変更される訳ではありません。実行結果はこうなります。

find ./ -type f | sed 'p;s/aaaa/bbbb/'
.//aaaa001.txt
.//bbbb001.txt
.//aaaa002.txt
.//bbbb002.txt
.//aaaa003.txt
.//bbbb003.txt

次にxargsコマンドで、それまでのコマンドの出力結果を引数として利用しmvコマンドを実行します。出力結果のうち2つずつをmvコマンドの引数として与える為(元のファイル名、変更後のファイル名)、-n2オプションを加えます。

実行結果はこうなります。

find ./ -type f | sed 'p;s/aaaa/bbbb/' | xargs -n2 mv
ls
bbbb001.txt	bbbb002.txt	bbbb003.txt

以上です。

2.for, find, mv, 変数展開で変更する方法

Facebookのお友達の桑畑さんにforと変数展開を用いた一括変更方法教えて頂いたので、調べて試してみました。桑畑さん、ありがとうございました^^

コマンドのテンプレートはこうなります。

for <変数:列挙するファイル名> in `find <検索対象ディレクトリのパス> -type f`; do mv <変数:列挙するファイル名> ${<変数:列挙するファイル名><置換条件>/<置換文字列>}; done

このうち、findに関する処理は1の場合と同様です。

forコマンドは、リストに対してループ処理を行います。今回はfindで検索した結果をリストとし、ループ処理を行い、ファイル名の変更処理を行います。

${<変数:列挙するファイル名><置換条件>/<置換文字列>}は、「変数展開」と呼ばれる処理のうちの1つで、文字の置換処理を行います。

実行結果はこうなります。

ls
aaaa-001.txt	aaaa-002.txt	aaaa-003.txt
for filename in `find . -type f`; do mv $filename ${filename/aaaa/bbbb}; done
ls
bbbb-001.txt	bbbb-002.txt	bbbb-003.txt

以上です。