2012年1月28日土曜日

【bash知恵袋】lsループで、半角スペースが入ったファイル名を正しく処理する

問題


bashでファイルを一括処理したい場合、下記のようなforループをよく使います。

例:拡張子を.txtから.csvに一括変更
for file in `ls *.txt`; do
  mv "${file}" "${file#.txt}.csv";
done


ところがファイル名に半角スペースが含まれていると、このスクリプトはうまく動きません。スペースも区切り文字として認識されて余計なループが発動してしまうためです。

解決法


こちらの掲示板で、この問題について議論されていました。
いくつかの解決策が提示されていますが、個人的に気に入ったのが"IFS"という環境変数を変更する方法です。(評価ポイントは1コマンドの追加だけで対応できる点)

(
IFS=$'\n';
for file in `ls *.txt`; do
  mv "${file}" "${file#.txt}.csv";
done
)

区切り文字を改行(\n)に限定することで、半角スペースを含んだファイル名も正しくループされます。
ちなみに、IFS環境変数の変更を局所化するために、処理全体をブラケット"()"で囲んでいます。これを忘れると以降の処理に影響するのでご注意ください。

おまけ

"IFS"って一体なんなのよ?と気になったので調べてみました。"Internal Field Separater"の略で、その名の通りシェルの内部でコマンドライン引数の区切り文字を定義する環境変数だそうです。デフォルトではスペース(" ")・タブ("\t")・改行("\n")に設定されています。

0 件のコメント:

コメントを投稿