
大量のファイルをシェルのコマンドで一括リネームする
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
大量のファイルを一括でリネームする場合、もしリネーム手順が簡素であれば、専用のスクリプトを書いたり、リネーム用のツールを使ったりせずともワンライナーで処理することができます。
前提
- リネーム対象のファイルを一つのフォルダにまとめている。
- 上記フォルダにリネーム対象ファイル以外の余分なファイルは含まれていない。
- 上記フォルダを作業ディレクトリとする。
- 作業は全て Mac OS X で行う。
目次
Case 1. 元のファイル名に文字を加える
対象ファイル
| 現在のファイル名 | リネーム後のファイル名 | 
|---|---|
| 001.txt | 001_document.md | 
| 002.txt | 002_document.md | 
| 003.txt | 003_document.md | 
| 004.txt | 004_document.md | 
| 005.txt | 005_document.md | 
| …… | …… | 
| 999.txt | 999_document.md | 
コマンド
$ ls | sed -e s/\.txt// | awk '{print $1 ".txt " $1 "_document.md"}' | xargs -n 2 mv
戦略について
まず前提として、ファイルのリネームを行うには、 xargs -n 2 mv にパイプで 元ファイル名 リネーム後のファイル名 のようなフォーマットの文字列を渡せば OK です。
$ ls before.txt $ echo "before.txt after.txt" before.txt after.txt $ echo "before.txt after.txt" | xargs -n 2 mv $ ls after.txt
この文字列が複数行ある場合、 xargs -n 2 mv は1行ずつ順次処理します。
$ ls 1.txt 2.txt $ echo "1.txt 11.txt\n2.txt 22.txt" 1.txt 11.txt 2.txt 22.txt $ echo "1.txt 11.txt\n2.txt 22.txt" | xargs -n 2 mv $ ls 11.txt 22.txt
ならば、今回の目標は以下のような複数行の文字列を作成し、 xargs -n 2 mv にパイプで食わせることです。
001.txt 001_document.md 002.txt 002_document.md 003.txt 003_document.md 004.txt 004_document.md 005.txt 005_document.md (中略) 999.txt 999_document.md
まず最初に、ls と sed を使って、フォルダ内に含まれる 拡張子を除く ファイル名の一覧を作ります。
$ ls | sed -e s/\.txt// 001 002 003 004 005 (中略) 999
次に awk を使って、ファイル名をマッピング文字列に変換します。
$ ls | sed -e s/\.txt// | awk '{print $1 ".txt " $1 "_document.md"}'
001.txt 001_document.md
002.txt 002_document.md
003.txt 003_document.md
004.txt 004_document.md
005.txt 005_document.md
(中略)
999.txt 999_document.md
※ これらの処理を一つの awk 命令にまとめることもできます。しかし便利な反面、学習コストが大きいため、今回は awk の使用を最小限にとどめています。
これで目標としていた文字列が完成したので、あとは xargs -n 2 mv に食わせれば OK です。
$ ls | sed -e s/\.txt// | awk '{print $1 ".txt " $1 "_document.md"}' | xargs -n 2 mv
$ ls
000_document.md  200_document.md  400_document.md  600_document.md  800_document.md
001_document.md  201_document.md  401_document.md  601_document.md  801_document.md
002_document.md  202_document.md  402_document.md  602_document.md  802_document.md
003_document.md  203_document.md  403_document.md  603_document.md  803_document.md
004_document.md  204_document.md  404_document.md  604_document.md  804_document.md
005_document.md  205_document.md  405_document.md  605_document.md  805_document.md
………
…
ファイルの一括リネームが完了しました。
Case 2. 元のファイル名に昇順で数字を追加する
対象ファイル
| 現在のファイル名 | リネーム後のファイル名 | 
|---|---|
| a.txt | 01_a.txt | 
| b.txt | 02_b.txt | 
| c.txt | 03_c.txt | 
| d.txt | 04_d.txt | 
| e.txt | 05_e.txt | 
| …… | …… | 
| z.txt | 26_z.txt | 
コマンド
$ ls | nl | awk '{ printf("%s %02d_%s\n", $2, $1, $2) }' | xargx -n 2 mv
戦略について
基本的には、1. 元のファイル名に文字を加えると同じ戦略です。  xargs -n 2 mv にマッピング用の文字列を食わせます。
今回の目標になる文字列は以下のとおりです。
a.txt 01_a.txt b.txt 02_b.txt c.txt 03_c.txt d.txt 04_d.txt e.txt 05_e.txt (中略) z.txt 26_z.txt
1. 元のファイル名に文字を加えると異なるのは、あたらしくファイルのナンバリングを行う部分です。
まず、ls | nl で行番号つきのファイル一覧を表示します。
$ ls | nl
     1  a.txt
     2  b.txt
     3  c.txt
     4  d.txt
     5  e.txt
     (中略)
    26  z.txt
これらは awk に2つの引数として食わせることができます。ここでは、第一引数($1)が行番号、第二引数($2)が元のファイル名になります。
これで必要な情報が揃ったため、 awk でマッピング用の文字列に整形します。
$ ls | nl | awk '{ printf("%s %02d_%s\n", $2, $1, $2) }'
a.txt 01_a.txt
b.txt 02_b.txt
c.txt 03_c.txt
d.txt 04_d.txt
e.txt 05_e.txt
(中略)
z.txt 26_z.txt
今回は、数字をゼロ埋めする必要が合ったため printf を使いました。Cファミリーの言語を使ったことがある方にはおなじみの関数です。
これで目標としていたマッピング文字列が完成しました。あとは xargs -n 2 mv に食わせれば完了です。
$ ls | nl | awk '{ printf("%s %02d_%s\n", $2, $1, $2) }' | xargx -n 2 mv
$ ls
01_a.txt 03_c.txt 05_e.txt 07_g.txt 09_i.txt 11_k.txt 13_m.txt 15_o.txt 17_q.txt 19_s.txt 21_u.txt 23_w.txt 25_y.txt
02_b.txt 04_d.txt 06_f.txt 08_h.txt 10_j.txt 12_l.txt 14_n.txt 16_p.txt 18_r.txt 20_t.txt 22_v.txt 24_x.txt 26_z.txt
ファイルの一括リネームが完了しました。
Case 3. 元のファイル名に日付を加える
対象ファイル
| 現在のファイル名 | ファイルの作成日 | リネーム後のファイル名 | 
|---|---|---|
| a.txt | 2月11日 | 0211_a.txt | 
| b.txt | 2月12日 | 0212_b.txt | 
| c.txt | 2月13日 | 0213_c.txt | 
| d.txt | 3月20日 | 0320_d.txt | 
| e.txt | 3月21日 | 0321_e.txt | 
| …… | …… | |
| z.txt | 5月1日 | 0501_z.txt | 
コマンド
$ ls -l | grep -v total | awk '{ printf("%s %02d%02d_%s\n", $9, $6, $7, $9) }' | xargs -n 2 mv
戦略について
1. 元のファイル名に文字を加えるや2. 元のファイル名に昇順で数字を追加するで使った小技を用いた複合的なアプローチです。
grep -v total で ls -l の total 行を取り除いています。ls -l の実行結果が英語以外だったりすると、このワンライナーはうまく動作しないかもしれません。
1. や 2. を読んでくださった方にとっては説明が冗長になってしまうため、詳しい解説はしませんが、今までどおり ls -l の結果を元にマッピング用の文字列を生成して xargs -n 2 mv に食わせているだけです。
まとめ
簡単な一括リネームには xargs -n 2 mv を活用しましょう。
ではまた!












