しぐまろぐ

勉強したことや読んだ本について書きます。

シェル・ワンライナー160本ノック 問題3

問題3:ファイル名の一括変換

1 ~ 1000000という名前のファイルを作成したのち、ファイル名の頭に0をつけて7桁に揃える。
※ 1000000だと時間がかかるので以下1000で行う。

正答

$ ls | xargs -P2 rename 's/^/0000/;s/0*([0-9]{4})/$1/'

最初のs/^/0000/;で、ファイル名の先頭に4個の0をつける。
次のs/0*([0-9]{4})/$1/で、0から始まるファイル名の末尾4桁を抽出し、該当部分を()で囲んでグループ化し、$1で後方参照してリネームする。

別解

上記だけで結構時間を食ったので別解はまた後日。→ 2023.01.04追記。別解2のみ。

$ time seq -w 1000 | awk '{print $1,$1}' | sed 's/^0*/mv /' | xargs -P2 -I@ sh -c @
  • seqのwオプション:最も大きい桁に合わせて0埋めしてくれる。この場合、1〜999を1000に合わせて頭に0をつけて4桁にしてくれる。
  • awk : 次のawkで2列にコピーし、「$ mv 0001 0001」の引数部分「0001 0001」を作る。
  • sed 's/^0*/mv /' : seqのwオプションでゼロ埋めされた部分を取り除き、「mv 」に置き換える。これで「$mv 1 0001」ができる。
  • sh : シェルを呼び出して実行。ここは練習1.3.gでbashによるメタプログラミングを実行したみたいな感じ。

今後の方針

まだ問題3だけど結構時間かかっていて、仕事がある日に毎日やるのは厳しいので、一旦もう一度以下に取り組んでから戻ってくる方がいいかも(弱気)

その他メモ

  • lsコマンドだと時間がかかるので、$ find でファイルの確認をするように指示があるが、macだからかうまくいかない。以下のように引数をつけるよう怒られる。
usage: find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
       find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]

→ 2023.01.12追記:MacOSにfindutilsをインストールすることで、$ gfindでファイルを確認できるようになった。$ gfindとするのが面倒な場合は、~/.bashrcに別名を設定することで、$ findで実行できるようになる。

  • macにrenameが入っていなかったので入れた。
$ brew install rename