スペースが混じったファイル名、大文字小文字がそろっていない拡張子、連番のゼロ埋めがバラバラなファイル群——これらはシェルスクリプトや他ツールへ渡すときにエラーや予期しない挙動の原因になりやすいです。Linux では rename コマンドや mv を組み合わせることで、こうした命名規則の乱れを一括で修正できます。この記事では、実務でよく使うパターンをまとめます。
rename コマンドを使う前に:バージョンの確認
Linux の rename コマンドには大きく 2 種類あり、どちらがインストールされているかはディストリビューションによって異なります。書き方も変わるため、先に確認しておくと手順を間違えずに済みます。
- Perl 版(rename / prename):Debian 系(Ubuntu など)でよく使われます。Perl の正規表現が使えるため、柔軟な置換が可能です。
- util-linux 版:RHEL 系(AlmaLinux・Rocky Linux など)に標準で含まれることが多いです。引数の形式が Perl 版とは異なり、単純な文字列置換のみ対応しています。
次のコマンドでバージョンを確認できます。
rename --version
出力に Perl という文字が含まれていれば Perl 版です。含まれていなければ util-linux 版です。rename が見つからない場合は、which rename で存在を確認してから sudo apt install rename(Debian 系)または sudo dnf install util-linux(RHEL 系)でインストールできます。
rename を使った文字列置換
スペースをアンダースコアに置き換える
ファイル名にスペースが含まれていると、シェルスクリプトの引数として渡すときにクォートが必要になり、処理が複雑になります。スペースをアンダースコアに統一するには次のコマンドが使えます。
rename 's/ /_/g' *
s/ /_/g は「スペースをアンダースコアに、すべての箇所で置き換える」という Perl の置換構文です。末尾の g フラグを省くと、最初に見つかったスペース 1 箇所だけが置換されます。
実行前に -n(または --no-act)オプションを付けると、実際にはリネームせず変更内容だけ表示するドライランになります。大量のファイルを処理する前に必ず確認しておくと安全です。
rename -n 's/ /_/g' *
大文字を小文字に統一する
拡張子の大文字小文字が混在している場合(.JPG と .jpg が混じっているなど)は以下のように対応できます。
Perl 版の場合:
rename 'y/A-Z/a-z/' *.JPG
y/A-Z/a-z/ は、ファイル名中のすべての大文字を対応する小文字に変換する構文です。ファイル名全体を小文字にそろえたい場合も同様に使えます。
util-linux 版の場合:
rename .JPG .jpg *.JPG
こちらは「.JPG という文字列を .jpg に置き換える」という単純な文字列置換です。正規表現は使えませんが、拡張子の単純な置換には手軽に使えます。
for ループと mv を使う方法
rename が使えない環境や、条件を細かく制御したい場合は、for ループと mv を組み合わせる方法が使えます。bash が使える環境であれば追加パッケージは不要です。
次の例は、カレントディレクトリの .txt ファイルの拡張子を .log に変更します。
for f in *.txt; do
mv "$f" "${f%.txt}.log"
done
${f%.txt} はシェルのパラメータ展開で、変数 f から末尾の .txt を取り除いた文字列を返します。mv の引数をダブルクォートで囲むことで、ファイル名にスペースが含まれていても正しく動作します。
実行前に動作を確かめたいときは、mv の代わりに echo mv を使うとドライランになります。コマンドを実行するのではなく、実行予定のコマンドをそのまま画面に出力するだけなので、ファイルへの変更は一切行われません。
for f in *.txt; do
echo mv "$f" "${f%.txt}.log"
done
連番ファイルのゼロ埋めリネーム
file1.txt・file2.txt・file10.txt のように連番の桁数がそろっていないと、ls の出力や sort の結果が期待どおりにならないことがあります。printf を使ってゼロ埋めしながらリネームできます。
次の例は file1.txt ~ file20.txt を file001.txt ~ file020.txt にリネームする想定例です。実際のファイル名のパターンに合わせて変更してください。
i=1
for f in file*.txt; do
mv "$f" "$(printf 'file%03d.txt' $i)"
i=$((i + 1))
done
printf 'file%03d.txt' $i の %03d は「3桁のゼロ埋め整数」を意味します。4桁にしたい場合は %04d に変更します。ループの前に ls file*.txt でファイルの処理順序を確認しておくと安全です。
プレフィックスを一括で付与する
ファイルを種別や環境ごとに整理したいとき、先頭に統一した文字列を付けることがあります。次の例は、カレントディレクトリの .log ファイルすべてに prod_ というプレフィックスを付けます。
for f in *.log; do
mv "$f" "prod_${f}"
done
Perl 版の rename では次のように書けます。
rename 's/^/prod_/' *.log
s/^/prod_/ は「ファイル名の先頭(^)に prod_ を挿入する」という意味です。今日の日付をプレフィックスにしたい場合は、次のようにシェルの機能と組み合わせることもできます。
TODAY=$(date +%Y%m%d)
for f in *.log; do
mv "$f" "${TODAY}_${f}"
done
date +%Y%m%d は実行時の日付を 20261112 のような形式で返します。バックアップファイルやログの整理など、日付で管理したいファイルに応用できます。
よくあるつまずきと対処
- 「Argument list too long」エラーになる:
*でファイルを指定すると、ファイル数が多すぎて引数が長くなりすぎる場合があります。find . -maxdepth 1 -name '*.txt' | xargs rename 's/ /_/g'のようにfindとxargsを組み合わせると回避できます。 - サブディレクトリのファイルも対象にしたい:
find . -name '*.txt' -exec rename 's/ /_/g' {} \;のように書くと再帰的に処理できます。-maxdepthで階層を制限するとより安全です。 - リネーム後にファイルが重複する:同名のファイルが既に存在するとき、
mvはデフォルトで上書きします。mv -i(確認あり)やmv -n(上書きしない)を使うと意図しない上書きを防げます。 - Perl 版と util-linux 版で構文が違う:複数のサーバー環境で同じスクリプトを使う場合は、
forループとmvの組み合わせを採用するとどちらの環境でも動作します。
大量のファイルを対象にする前は、ドライランで変更内容を確認してから本番実行することを推奨します。
「コマンドは打てる。次は”現場で通用する型”を最短で身につけたい」——そんなあなたへ。
ネットの断片的なTipsをコピペするだけでは、体系的な運用スキルはなかなか積み上がりません。リナックスマスター.JPの無料メルマガ「リナマガ」では、現場で実際に使うLinuxサーバー運用の考え方を、順を追って実務目線でお届けしています。いま登録された方には、安全なサーバー構築の「型」をまとめた『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼント中です。
>> 図解60P『Linux入門マニュアル』を無料で受け取る
(メルマガ登録は10秒・いつでも解除OK)
※ 「独学の時間がもったいない」「プロから現場の技術を最短で学びたい」という本気の方には、2日で実務レベルが身につく初心者向けハンズオンセミナーもご用意しています。
