使用Bash重命名文件格式的最佳方法是什么:
(foo1, foo2, ..., foo1300, ..., fooN)
使用零填充文件名:
(foo00001, foo00002, ..., foo01300, ..., fooN)
答案 0 :(得分:55)
这不是纯粹的bash,但使用rename
命令更容易:
rename 's/\d+/sprintf("%05d",$&)/e' foo*
答案 1 :(得分:27)
如果N
不是先验固定的:
for f in foo[0-9]*; do mv $f `printf foo%05d ${f#foo}`; done
答案 2 :(得分:18)
我有一个更复杂的案例,文件名有一个后缀和一个前缀。我还需要对文件名中的数字进行减法。
例如,我希望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
答案 3 :(得分:5)
我使用的oneline命令是:
ls * | cat -n | while read i f; do mv "$f" `printf "PATTERN" "$i"`; done
PATTERN可以是例如:
%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
答案 4 :(得分:4)
Pure 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
答案 5 :(得分:2)
以下将会这样做:
for ((i=1; i<=N; i++)) ; do mv foo$i `printf foo%05d $i` ; done
编辑:已更改为使用((i = 1,...)),感谢mweerden!
答案 6 :(得分:0)
这是一个快速的解决方案,它假设一个固定长度的前缀(你的“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
答案 7 :(得分:0)
我的解决方案替换字符串中的数字中的数字
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(不是数字)相反,然后用空替换{{1}将其删除}。为什么不删除//
?由于文件名可以包含点,破折号等。因此,我们剥离所有内容,即不是数字的数字,然后获取数字。
接下来,我们将结果分配给[a-z]
变量。请记住不要像number
那样分配空格,因为您会得到不同的行为。
我们将命令的执行结果分配给变量,并用反引号将命令包装起来。
命令number = …
将数字格式更改为4位数字,如果我们的数字少于4位数字,则添加零。
我们再次将printf "%04d" $number
与sed
之类的替换命令一起使用。为了解释变量,我们使用双引号并以s/substring/replacement/
的方式替换变量。
上面的脚本仅显示转换后的名称,因此,让我们进行实际的重命名工作:
${number}
希望这对某人有帮助。
我花了几个小时来解决这个问题。
答案 8 :(得分:0)
到文件名中的左键数字:
$ 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}\`
(正上方的反斜杠\只是将单线分隔为两行以提高可读性)[0-9]*.[a-z]*
$f
)并将其传递给awk
-F.
:awk
字段分隔符,以句点(.
)表示:如果匹配,则将文件名分隔为两个字段($1
=数字; {{1} } =扩展名)$2
的格式:将第一个字段(printf
,数字部分)打印为4位数字($1
),然后打印句点,然后打印第二个字段({{1 }}:扩展名)作为字符串(%04d
。所有这些都分配给$2
变量%s
)移到新文件名($tmp
)