特に初歩的ですが、備忘録。
達成したいこと
こんなファイル列があり、これを降順にナンバリングしたい
~❯ ls
IMG_20251109_084220.jpg IMG_20251109_084300.jpg IMG_20251109_084337.jpg
IMG_20251109_084223.jpg IMG_20251109_084303.jpg IMG_20251109_084352.jpg
IMG_20251109_084228.jpg IMG_20251109_084314.jpg IMG_20251109_084435.jpg
IMG_20251109_084234.jpg IMG_20251109_084327.jpg IMG_20251109_084457.jpg
以下のようにrenameしたいというときです。
~❯ ls smartphone
smartphone_10.jpg smartphone_2.jpg smartphone_5.jpg smartphone_8.jpg
smartphone_11.jpg smartphone_3.jpg smartphone_6.jpg smartphone_9.jpg
smartphone_1.jpg smartphone_4.jpg smartphone_7.jpg
解決方法
まずはsortします。
lsのstdoutをpipeでsortのstdinに流します。
~❯ ls | sort
IMG_20251109_084220.jpg
IMG_20251109_084223.jpg
IMG_20251109_084228.jpg
IMG_20251109_084234.jpg
IMG_20251109_084300.jpg
IMG_20251109_084303.jpg
IMG_20251109_084314.jpg
IMG_20251109_084327.jpg
IMG_20251109_084337.jpg
IMG_20251109_084352.jpg
IMG_20251109_084435.jpg
IMG_20251109_084457.jpg
連番じゃないので上から処理する必要があります。
なのでforを使って処理します。
基本的なforの使い方は
for 変数 in リスト; do
コマンド群
done
であるから、リストにファイル名が来て、変数にファイル名1つが取れたらOK。
$()はコマンド置換。つまりさっきのls | sortが展開されます。
for filename in $(ls | sort);
do
mv "$filename" "smartphone_.jpg"
done
ですが、ナンバリングできてません。
調べるとイテレータをそのまま取得できないようなのでカウント変数を用意します。
i=1
for filename in $(ls | sort);
do
mv "$filename" "smartphone_${i}.jpg"
((i++))
done
これで期待している操作が行えます。
補足
-
変数の扱い
-
"$filename"
最も安全です。つまり展開後は"IMG_20251109_084220.jpg"となります。 -
$filename
危険です。この場合の展開後は先述と同じですが、filenameに空白がある場合は
mv IMG 20251109_084220.jpg hoge
と解釈され、コマンドライン引数に不正が生じ、解釈に失敗します。 -
filename
間違いです。この場合は当たり前ですが、mv filename hogeと解釈されます。
-
-
カウントアップについて
-
i = i + 1
NG。 iコマンドの引数として = i + 1がコマンドライン引数で渡されたと解釈します。 -
i=$((i + 1))
OK。純粋な書き方です。 -
((i += 1))
上記省略形です。 -
((i++))
インクリメント省略形です。
-
以上です。