シェルで大量のファイルの名前を一括で変更しようとしています。インターネット上にたくさんの資料がありますが、特定のケースの解決策が見つからないようです。
「タイムスタンプID」(と思われるもの)を持つファイルがたくさんあります。
abc_128390.png
abc_138493.png
abc_159084.png
...
カウンターと交換したいこと:
abc_001.png
abc_002.png
abc_003.png
...
私の(たくさんの)素朴なアプローチは次のようなものです:
mv abc_*.png abc_{001..123}.png
また、for
- loopで機能させる方法を理解できませんでした。
FWIW、残念ながらrename
はこの特定のシステムでは利用できません。
何かアドバイスをいただければ幸いです!
もっと賢い方法でカウンターをインクリメントするソリューションを考えることはできませんが、これはうまくいくはずです:
i=0
for fi in abc_??????.png; do
mv "$fi" abc_$i.png
i=$((i+1))
done
abc_*.png
は最初のmv
が実行される前に展開されるため安全に使用できるはずですが、6文字のタイムスタンプを持つファイルのみが必要なため、終わり。
Perlパッケージの一部としてrename
ユーティリティを使用すると、次のようになります。
rename -n 'our $i; s/_.*/sprintf("_%03d.png", $i++)/e' *.png
注:-n
は予行演習用です。ファイルの名前を変更するには、それを削除してください。
zsh
の場合:
typeset -A count
incr='++count[$1/$2]'
(zmv -n '([^0-9]##)<->(*)(#qn)' '$1${(l:3::0:)$((incr))}$2')
満足したら-n
を削除します。
例:
$ ls
a1b.png abc_128390.png abc_159084.png x12y.png
a2b.png abc_138493.png a.png x2y.png
$ typeset -A count
$ incr='++count[$1/$2]'
$ (zmv -n '([^0-9]##)<->(*)(#qn)' '$1${(l:3::0:)$((incr))}$2')
mv -- a1b.png a001b.png
mv -- a2b.png a002b.png
mv -- abc_128390.png abc_001.png
mv -- abc_138493.png abc_002.png
mv -- abc_159084.png abc_003.png
mv -- x2y.png x001y.png
mv -- x12y.png x002y.png
既存のファイルを上書きしないでください:
i=1
for fi in abc_??????.png; do
a="abc_$(printf '%04d' "$i").png"
if [[ -e $a ]]; then
echo "file $a exist, not moving $fi"
else
mv "$fi" "$a"
fi
i=$((i+1))
done
たとえば、ファイル名を次のように変更したい場合は、cutを使用してファイル名の一部を切り取ることができます。
"1 first.jpg"
"2 second.jpg"
...
に
"10 first.jpg"
"20 second.jpg"
...
あなたは使うことができます
for i in *jpg; do
mv -iv "$i" "$(echo "$i"|cut -d\ -f1)0 $(echo "$i"|cut -d\ -f2-99)";
done