min117の日記

初期desireもち。趣味Mac,メインFedora,仕事xp。

bash サブシェルを利用してファイル名の区切り文字IFSを一時的に変更する

f:id:min117:20200103104627p:plain

 

素晴らしいサイトを見つけた。年始から幸先良い。

qiita.com

 

困っていたのはこれ。

rougeref.hatenablog.com

bashの区切り文字(IFS)は標準では「スペース(空白)とタブと改行」になってしまっているので、例えばfor文で複数ファイルに一括処理を回すときに空白を含むファイル名をうまく扱えない。

 

例えばこんなmp3があったとする。

f:id:min117:20200119103306p:plain

ファイル名に大量に 半角スペース を含んでいる。

 

これを for文 に食わせてみるとこうなっちゃう。

$ for i in $(ls -rt | grep mp3 | tail -n 3); do echo "$i"; done

f:id:min117:20200119103448p:plain

3曲だけ取り出せるはずが、1曲が(スペースでぶった切られて)バラバラになってしまっている。

これはファイル名の区切り文字(IFS)を「スペースとタブと改行」じゃなくて「改行だけ」に変更すればいいわけだが、たとえばこのサイトみたいに、OLDIFSに退避してあとから戻すようなのはダルい。

f:id:min117:20200103101755p:plain

あくまで一時的にIFSを変更したいだけ。

 

これを実現するやり方が冒頭サイトにあった。サブシェルを使えば一時的にIFSを変更できるらしい。どの世界にもプロがいるものだ。 

f:id:min117:20200103100936p:plain

 

やってみる。

 

まず、現在のIFSを確認するにはこのコマンドを使う。

$ echo -n "$IFS" | od -b

qiita.com

 

サブシェルを使ってIFSを変更してみる。

$ echo -n "$IFS" | od -b

$ ( IFS=$'\n'; echo -n "$IFS" | od -b )

$ echo -n "$IFS" | od -b

f:id:min117:20200103103942p:plain

なんてこった。素晴らしい。一時的なIFSの変更がワンライナーできた。

 

さっきのmp3に適用してみる。

$ ( IFS=$'\n'; for i in $(ls -rt | grep mp3 | tail -n 3); do echo "$i"; done; )

f:id:min117:20200119103930p:plain

グッハ素晴らしい。できた。最高。

 

前後のIFSの動きも見てみよう。

$ echo -n "$IFS" | od -b

$ ( IFS=$'\n'; for i in $(ls -rt | grep mp3 | tail -n 3); do echo "$i"; done; )

$ echo -n "$IFS" | od -b

f:id:min117:20200119104347p:plain

これは良い。かなり重宝しそう。

 

IFSをデフォルトの「スペースとタブと改行」に戻すには

IFS="$'\n'$'\t' "

n9d.hatenadiary.org

f:id:min117:20200119105548p:plain