我正在尝试重命名一批格式的文件:
test1_run1
test1_run2
...
test1_run10
...
test10_run1
test10_run2
...
test10_run10
到具有多个填充的表单。对于第一个数字,我需要填充长度为零的零,而第二个长度为3。
最终结果应采用以下形式:
test00001_run001
test00001_run002
...
test00001_run010
...
test00010_run001
test00010_run002
...
test00010_run010
如何在bash中为特定文件夹中的所有文件执行此操作?
答案 0 :(得分:1)
在bash中:
#!/bin/bash
shopt -s nullglob extglob
for file in test+([[:digit:]])_run+([[:digit:]]); do
[[ $file =~ ^test([[:digit:]]+)_run([[:digit:]]+)$ ]]
printf -v newfile 'test_%05d_run%03d' "$((10#${BASH_REMATCH[1]}))" "$((10#${BASH_REMATCH[2]}))"
echo mv "$file" "$newfile"
done
从要处理的文件夹中运行此操作。这只会echo
执行mv
个命令。如果您对结果感到满意,请移除echo
。
nullglob
,以便不匹配的globs扩展为空; extglob
,因为for
循环将使用扩展的glob; test+([[:digit:]])_run+([[:digit:]])
将扩展为与此模式匹配的文件(如果有)BASH_REMATCH[1]
,第二个位于BASH_REMATCH[2]
。printf
格式化新文件名;修饰符%05d
和%03d
将根据您的意愿格式化数字(使用适当的前导零)。请注意,如果您有文件((10#${BASH_REMATCH[1]}))
,我们会使用test09_run001
明确指定该数字是基数为10。 09
部分会使bash误解基数8中的数字(因为前导0)并且您会收到投诉; -v
开关告诉printf
不在标准输出上输出,而是将输出存储在变量newfile
中; mv
。答案 1 :(得分:1)
我们可以将字符串转换为test
+ 5 digits
+ _run
+ 3 digits
格式,然后说:
$ awk -F"test" '{split($2,a,"_run"); printf "%s%0.5d%s%0.3d\n", FS, a[1], "_run", a[2]}' a
test00001_run001
test00001_run002
test00001_run010
test00010_run001
test00010_run002
test00010_run010
这可以通过使用test
作为字段分隔符并将第二个字段分为两部分来实现:_run
之前和之后。然后,它使用printf
个东西来获得正确的输出。
然后,您可以将mv
与之前的值一起打印并说:
$ awk -F"test" '{split($2,a,"_run"); printf "mv %s %s%0.5d%s%0.3d\n", $0, FS, a[1], "_run", a[2]}' a
mv test1_run1 test00001_run001
mv test1_run2 test00001_run002
mv test1_run10 test00001_run010
mv test10_run1 test00010_run001
mv test10_run2 test00010_run002
mv test10_run10 test00010_run010
如果然后将其传送到sh
,它将被执行。
答案 2 :(得分:1)
如果您不想使用perl或awk,并且严格使用bash和大多数发行版中提供的一些实用程序,您可以尝试这样的事情:
for i in * ; do
testpart=`echo $i | cut -d_ -f1`
testnum=${testpart#test}
runpart=`echo $i | cut -d_ -f2`
runnum=${runpart#run}
destfile=test`printf %05d $testnum`_run`printf %03d $runnum`
mv $i $destfile
done