使用 Bash 以以下形式重命名文件的最佳方法是什么:
(foo1, foo2, ..., foo1300, ..., fooN)
使用零填充文件名:
(foo00001, foo00002, ..., foo01300, ..., fooN)
它不是纯 bash,但使用 Perl 版本的rename
:
rename 's/\d+/sprintf("%05d",$&)/e' foo*
's/\d+/sprintf("%05d",$&)/e'
Perl 替换正则表达式在哪里。
\d+
将匹配第一组数字(至少一个数字)sprintf("%05d",$&)
将匹配的数字传递给 Perl's sprintf
,%05d
并将填充到五位数如果N
不是先验固定的:
for f in foo[0-9]*; do
mv "$f" "$(printf 'foo%05d' "${f#foo}")"
done
我有一个更复杂的情况,文件名有后缀和前缀。我还需要从文件名中减去数字。
例如,我想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
例如,模式可以是:
%04d.${f#*.}
保留原始文件扩展名)photo_%04d.${f#*.}
保留原始扩展名)%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
To left-pad numbers in filenames:
$ 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
Explanation
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}\`
(The backslash, \, immediately above just splits that one-liner over two lines for readability)[0-9]*.[a-z]*
$f
) to pass it to awk
-F.
: awk
field separator, a period (.
): if matched, separates the file names as two fields ($1
= number; $2
= extension)printf
: print first field ($1
, the number part) as 4 digits (%04d
), then print the period, then print the second field ($2
: the extension) as a string (%s
). All of that is assigned to the $tmp
variable$f
) to the new filename ($tmp
)纯 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,...)),谢谢mweerden!
This answer is derived from Chris Conway's accepted answer but assumes your files have an extension (unlike Chris' answer). Just paste this (rather long) one liner into your command line.
for f in foo[0-9]*; do mv "$f" "$(printf 'foo%05d' "${f#foo}" 2> /dev/null)"; done; for f in foo[0-9]*; do mv "$f" "$f.ext"; done;
OPTIONAL ADDITIONAL INFO
This script will rename
foo1.ext > foo00001.ext
foo2.ext > foo00002.ext
foo1300.ext > foo01300.ext
To test it on your machine, just paste this one liner into an EMPTY directory.
rm * 2> /dev/null; touch foo1.ext foo2.ext foo1300.ext; for f in foo[0-9]*; do mv "$f" "$(printf 'foo%05d' "${f#foo}" 2> /dev/null)"; done; for f in foo[0-9]*; do mv "$f" "$f.ext"; done;
This deletes the content of the directory, creates the files in the above example and then does the batch rename.
For those who don't need a one liner, the script indented looks like this.
for f in foo[0-9]*;
do mv "$f" "$(printf 'foo%05d' "${f#foo}" 2> /dev/null)";
done;
for f in foo[0-9]*;
do mv "$f" "$f.ext";
done;
这是一个快速的解决方案,它假设一个固定长度的前缀(你的“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