我有几个使用此模式的文件:prefix.1.*
,prefix.2.*
,prefix.3.*
等...我希望他们的名字分别更改为prefix.01.*
,prefix.02.*
,prefix.03.*
等。这样,它们将按名称正确排序,因为集合中已有两位数(例如prefix.27.*
)的文件名。
如何使用bash shell中提供的命令来实现?
注意:就在这个问题之后,我不得不处理一个文件列表,例如prefix.1.*
,prefix.2.*
,prefix.17.*
,prefix.157.*
(任意,不按顺序编号) ,目的是使用插入正确数量的前导零的通用方式转换为prefix.001.*
,prefix.002.*
,prefix.017.*
,prefix.157.*
。如果您遇到这种情况,我强烈建议您遵循以下mklement0 answer(更通用的重命名解决方案)提供的一般解决方案。
答案 0 :(得分:3)
for file in prefix.[0-9].*
do
mv "$file" "${file/prefix./prefix.0}"
done
答案 1 :(得分:2)
更通用的重命名解决方案,由OP后来的评论提示
使用基于Perl的rename
实用程序,它是某些 Linux发行版(例如,Ubuntu)的标准配置。 警告:某些发行版具有util-linux
包中同名的不同实用程序。
在OS X上,您可以使用brew install rename
通过Homebrew进行安装。
两种解决方案都会动态确定所需的填充宽度 。
printf '%s\n' prefix.[0-9]*.* | # enumerate files of interest
sort -t. -n -k2,2 | # sort them by the embedded number
rename -n -N '...01' -e 's/\.\d+\./.$N./' # rename with appropriate padding
-n
仅执行干运行,仅显示会发生的事情;删除它以执行实际重命名-N '...01'
以根据输入文件数自动确定适当的零填充的方式指定特殊计数器变量$N
的格式。's/\.\d+\./.$N./'
是一个Perl表达式,用适当填充的计数器变量$N
替换现有的数字组件。在这种情况下,填充宽度来自文件名中嵌入的最大现有数字:
# Determine the longest (largest) number contained in the matching filenames...
maxNum=$(printf '%s\n' prefix.[0-9]*.* | sort -nrt. -k2,2 | head -1 | cut -d. -f2)
# ... and derive the padding length from it.
padLength=${#maxNum}
# Perform renaming by zero-padding the *existing* numbers in the filenames.
rename -n -e 's/\.(\d+)\./sprintf(".%0'${padLength}'s.", $1)/e' prefix.[0-9]*.*
-n
仅执行干运行,仅显示会发生的事情;删除它以执行实际重命名e
命令中使用Perl的s/.../.../
标志,该标志允许在替换字符串中使用任意Perl表达式;在这种情况下,sprintf
表达式用于填充输入数字;这种方法的功劳属于@AdrianFrühwirth的回答here。总的来说,使用shopt -s extglob
和prefix.+([0-9]).*
可以使匹配的文件名更加健壮;同样,shopt -s nullglob
可以更轻松地确定任何文件是否匹配。
答案 2 :(得分:1)
请注意纯bash
解决方案,但更简洁(*):
printf '%s\0' prefix.[0-9].* |
xargs -0 -I % bash -c 'f="%"; mv "$f" "${f/\./.0}"'
这假设glob prefix.[0-9].*
扩展到至少1个实际文件名
如果NO文件可能匹配,请先执行shopt -s nullglob
(如果需要,稍后再恢复该shell选项的值)。
效果记录:
虽然这比<{3}}更简洁,但由于每个人都会生成一个额外的子shell(bash -c
),因此表现更差输入文件名 - 以便能够将文件名分配给变量并在其上使用扩展。
(*)就字符数而言,@R Sahu's solution实际上更短,但缺少循环(以及更少的行)可能会导致此答案被感知< / em>更短。在一天结束时,这个解决方案本身并没有多少 - 除了作为使用xargs
的高级示例之外:
printf '%s\0'
确保所有匹配的文件名都通过NUL字符传递给管道。作为分隔符。xargs -0
然后确保单独识别文件名,即使它们包含嵌入的空格。-I %
确保每个输入文件名导致其自己调用后面的命令,其中%
个实例替换为手头的文件名。bash -c
然后调用子shell(恰好是另一个bash
实例的子进程)并评估指定的字符串。答案 3 :(得分:0)
我找到的最简单的方法就是在bash shell中输入这一行:
for ITER in 1 2 3 4 5 6 7 8 9; do for FILE in prefix."$ITER".*; do mv "$FILE" $(echo "$FILE" | sed 's/prefix.'$ITER'/prefix.0'$ITER'/'); done; done
答案 4 :(得分:0)
另一种方式&gt;&gt;
#!/bin/bash
count=1
for i in $(ls prefix*)
do
Newname=prefix\.$(printf "%02d" $count)\.txt
mv $i $Newname
count=$(($count + 1))
done
答案 5 :(得分:0)
到目前为止,很好的答案。如果所有文件的扩展名都相同。只需使用以下。这里的扩展名是.jpg
您可以将prefix_
更改为您选择的前缀。
另外,如果您想要更多的前导零,只需将%02更改为%03,依此类推。
rename -n -e 's/\d+/sprintf("prefix_%02d",$&)/e' -- *.jpg