[シェル芸][linux]ファイル名のスペースとアンダースコアを置換する


profile-photo-usptomo-96x96みなさんこんにちは。久々にゲラで笑う飲みがありまして、顔の筋肉が大変なことになっています。飲み会で撮った写真を手元のマシン(CentOS)で編集するのに、iPhoneからDropboxを経由して同期しており大変便利なのですが、iPhoneで自動的につけられるファイル名にスペースが複数含まれており、コマンドラインからの操作がちょっと面倒です。しかしそこはシェル芸でファイル名を変更してしまいましょう。

さて、写真があるディレクトリですが、ご覧のように他の参加者からもらったファイルも含めて、ファイル名の規則がバラバラだったりします。

[ (っ´∀`)っ@友の会 ~]$ ls | sort
1081356_10200364337474395_170357340_n.jpg
写真 2013-07-30 21 17 09.jpg
写真 2013-07-30 21 17 48.jpg
写真 2013-07-30 21 29 51.jpg
写真 2013-07-30 21 30 26.jpg
写真 2013-07-30 21 31 00.jpg
写真 2013-07-30 21 31 07.jpg
写真 2013-07-30 21 31 10.jpg
写真 2013-07-30 21 31 55.jpg
写真 2013-07-30 21 32 07.jpg
写真 2013-07-30 21 32 28.jpg
写真 2013-07-30 21 32 44.jpg
写真 2013-07-30 21 33 01.jpg
写真 2013-07-30 21 33 10.jpg

iPhoneで撮影した写真のファイル名は「写真 YYYY-MM-DD HH MM SS.jpg」という名前です。このように、1つのファイル名に複数のスペースが含まれています。同じディレクトリに、友達がfacebookにアップロードした写真も保存しています。こちらはファイル名にスペースを含んでおらず、アンダースコア(アンダーバー)が含まれています。

上記前提をあんまり考慮しないでファイル名を置換するとこうなります。

[ (っ´∀`)っ@友の会 ~]$ for A in $(ls | sed -e s/" "/_/g) ; do mv "$(echo $A | sed -e s/_/' '/g)" $A ; done
mv: cannot stat `1081356 10200364337474395 170357340 n.jpg': そのようなファイルやディレクトリはありません

結果としてスペースはアンダースコアに置換されましたが、エラーなく置換したいものです。というわけで、forに食わせる条件を変更してみましょう。

[ (っ´∀`)っ@友の会 ~]$ for A in $(ls | grep " " | sed -e s/" "/_/g) ; do mv "$(echo $A | sed -e s/_/' '/g)" $A ; done

これで先ほどのエラーは出なくなりました。しかし世の中あまのじゃくな人がいるもので、「この_っていうの見た目よくな~い。スペースにしておいて!」と怒られることもあるでしょう。思う所はありますが、そこは大人。「それならお前がやれ」と突き放して手mvさせてもよいですが、黙って一括置換してさしあげましょう。

[ (っ´∀`)っ@友の会 ~]$ for A in $(ls); do mv $A "$(echo $A | sed -e s/_/" "/g)"; done

例によって↑は、ディレクトリ内にあるファイルがすべてアンダースコアを含んでいる前提です。そうでなく、ファイル名の規則がバラバラであれば以下のようにしましょう。

[ (っ´∀`)っ@友の会 ~]$ for A in $(ls | grep _); do mv $A "$(echo $A | sed -e s/_/" "/g)"; done

こうしてとあるオフィスの人間関係を損なうことなく綺麗にファイルの整理ができました。お疲れ様でした。

[amazonjs asin="4774158135" locale="JP" title="Linuxシステム実践入門 (Software Design plus)"]