質問
Bash を使用して次の形式でファイルの名前を変更する最良の方法は何ですか。
(foo1, foo2, ..., foo1300, ..., fooN)
ファイル名にゼロが埋め込まれた場合:
(foo00001, foo00002, ..., foo01300, ..., fooN)
解決
万一に備えて N
は先験的に固定されていません:
for f in foo[0-9]*; do mv $f `printf foo%05d ${f#foo}`; done
他のヒント
純粋な bash ではありませんが、 rename
指示:
rename 's/\d+/sprintf("%05d",$&)/e' foo*
ファイル名に接頭辞だけでなく接尾辞も含まれる、より複雑なケースがありました。ファイル名から数値を減算する必要もありました。
たとえば、私が欲しかったのは、 foo56.png
なる foo00000055.png
.
もっと複雑なことをしている場合にこれが役立つことを願っています。
#!/bin/bash
prefix="foo"
postfix=".png"
targetDir="../newframes"
paddingLength=8
for file in ${prefix}[0-9]*${postfix}; do
# strip the prefix off the file name
postfile=${file#$prefix}
# strip the postfix off the file name
number=${postfile%$postfix}
# subtract 1 from the resulting number
i=$((number-1))
# copy to a new name with padded zeros in a new folder
cp ${file} "$targetDir"/$(printf $prefix%0${paddingLength}d$postfix $i)
done
私が使用する一行コマンドは次のとおりです。
ls * | cat -n | while read i f; do mv "$f" `printf "PATTERN" "$i"`; done
PATTERN には、たとえば次のようなものがあります。
- インクリメントカウンターを使用して名前を変更します。
%04d.${f#*.}
(元のファイル拡張子を保持します) - プレフィックス付きの増分カウンターを使用して名前を変更します。
photo_%04d.${f#*.}
(元の拡張子を保持します) - インクリメントカウンターを使用して名前を変更し、拡張子をjpgに変更します。
%04d.jpg
- プレフィックスとファイルのベース名を含む増分カウンターを使用して名前を変更します。
photo_$(basename $f .${f#*.})_%04d.${f#*.}
- ...
たとえば、名前を変更するファイルをフィルタリングできます。 ls *.jpg | ...
変数が利用可能になりました f
それはファイル名であり、 i
それがカウンターです。
あなたの質問に対する正しいコマンドは次のとおりです。
ls * | cat -n | while read i f; do mv "$f" `printf "foo%d05" "$i"`; done
純粋な Bash、「mv」以外の外部プロセスなし:
for file in foo*; do
newnumber='00000'${file#foo} # get number, pack with zeros
newnumber=${newnumber:(-5)} # the last five characters
mv $file foo$newnumber # rename
done
以下はそれを行います:
for ((i=1; i<=N; i++)) ; do mv foo$i `printf foo%05d $i` ; done
編集: ((i=1,...)) を使用するように変更されました、ありがとう ムールデン!
ここでは、固定長のプレフィックス (「foo」) と固定長のパディングを想定した簡単な解決策を示します。もっと柔軟性が必要な場合は、少なくともこれが出発点として役立つでしょう。
#!/bin/bash
# some test data
files="foo1
foo2
foo100
foo200
foo9999"
for f in $files; do
prefix=`echo "$f" | cut -c 1-3` # chars 1-3 = "foo"
number=`echo "$f" | cut -c 4-` # chars 4-end = the number
printf "%s%04d\n" "$prefix" "$number"
done
私のソリューションは数字を置き換えます。 文字列内のどこでも
for f in * ; do
number=`echo $f | sed 's/[^0-9]*//g'`
padded=`printf "%04d" $number`
echo $f | sed "s/${number}/${padded}/";
done
変換されたファイル名を出力するだけなので、簡単に試すことができます (ファイルシステムの操作は実行されません)。
説明:
ファイルのリストをループする
ループ: for f in * ; do ;done
, 、すべてのファイルをリストし、各ファイル名を次のように渡します。 $f
ループ本体に変数を追加します。
文字列から数値を取得する
と echo $f | sed
変数をパイプします $f
に sed
プログラム。
コマンドで sed 's/[^0-9]*//g'
, 、 一部 [^0-9]*
修飾子付き ^
数字 0 ~ 9 (数値ではない) の反対側に一致し、それを空の置換で削除するように指示します。 //
. 。なぜ単に削除しないのですか [a-z]
?ファイル名にはドットやダッシュなどが含まれる可能性があるためです。したがって、数値ではないものをすべて取り除き、数値を取得します。
次に、結果を次のように代入します。 number
変数。代入にスペースを入れないように注意してください。 number = …
, 、異なる動作が得られるためです。
コマンドの実行結果を変数に代入し、コマンドをバックティック記号 ` で囲みます。
ゼロパディング
指示 printf "%04d" $number
数値の形式を 4 桁に変更し、数値が 4 桁未満の場合はゼロを追加します。
数値をゼロ埋め数値に置き換える
を使用しております sed
再度次のような置換コマンドを使用します s/substring/replacement/
. 。変数を解釈するには、二重引用符を使用し、次のように変数を置き換えます。 ${number}
.
上記のスクリプトは変換された名前を出力するだけなので、実際の名前変更ジョブを実行してみましょう。
for f in *.js ; do
number=`echo $f | sed 's/[^0-9]*//g'`
padded=`printf "%04d" $number`
new_name=`echo $f | sed "s/${number}/${padded}/"`
mv $f $new_name;
done
これが誰かの役に立てば幸いです。
これを理解するのに数時間を費やしました。
ファイル名の数字を左詰めするには:
$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 1.zzz
$ for f in [0-9]*.[a-z]*; do tmp=`echo $f | awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
$ ls -l
total 0
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0001.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:23 0050.zzz
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 010
-rw-r--r-- 1 victoria victoria 0 Mar 28 18:09 050
-rw-r--r-- 1 victoria victoria 0 Mar 28 17:24 10
説明
for f in [0-9]*.[a-z]*; do tmp=`echo $f | \
awk -F. '{printf "%04d.%s\n", $1, $2}'`; mv "$f" "$tmp"; done;
- バッククォートに注意してください:
`echo ... $2}\`
(すぐ上のバックスラッシュ \ は、読みやすくするために 1 行を 2 行に分割しているだけです) - ループ内で、小文字のアルファベットの拡張子が付いた数字で名前が付けられたファイルを検索します。
[0-9]*.[a-z]*
- そのファイル名をエコーします (
$f
) に渡すawk
-F.
:awk
フィールド区切り文字、ピリオド (.
):一致した場合、ファイル名が 2 つのフィールドに分割されます ($1
= 数字;$2
= 拡張子)- でフォーマットする
printf
:最初のフィールドを出力 ($1
, 、数字部分)を4桁(%04d
)、次にピリオドを出力し、次に 2 番目のフィールド ($2
:拡張子) を文字列として (%s
)。そのすべてが割り当てられています$tmp
変数 - 最後に、ソース ファイルを移動します (
$f
) を新しいファイル名 ($tmp
)