Regex Bash正则表达式重命名文件
我有一堆文件,只是一个unix时间。问题是,它们的文件名变为millis,而扫描该目录的程序希望它们在几秒钟内就消失。因此,我需要重命名所有文件,以删除.txt扩展名之前的最后3位数字。即: 1461758015598.txt-->1461758015.txt 我不熟悉regex和bash,所以我不知道该怎么做。这里有一种方法:Regex Bash正则表达式重命名文件,regex,bash,rename,Regex,Bash,Rename,我有一堆文件,只是一个unix时间。问题是,它们的文件名变为millis,而扫描该目录的程序希望它们在几秒钟内就消失。因此,我需要重命名所有文件,以删除.txt扩展名之前的最后3位数字。即: 1461758015598.txt-->1461758015.txt 我不熟悉regex和bash,所以我不知道该怎么做。这里有一种方法: for f in *.txt; do mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}" done 在do和done之间,它一次
for f in *.txt; do
mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}"
done
在do
和done
之间,它一次查看一个文件,当前文件的名称位于参数f
中<代码>“$f”是该参数的值,未更改“${f/[0-9][0-9][0-9].txt/.txt}”
是应用替换的参数值:将“三位数后跟.txt
”替换为.txt
正如@anubhava所指出的,如果您多次运行它,它会不断删除文件名中的数字,所以不要这样做。通过收紧glob模式,可以使其幂等。这有点笨拙:
for f in [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].txt; do
mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}"
done
因此,您可能希望使用外部工具使其更加紧凑(这假设目录中的任何文件名中没有空格或换行):
您可以使用while read
循环将限制减少为“无换行”:
ls -1 | egrep '^[0-9]{13}\.txt$' | while read f; do
mv "$f" "${f/[0-9][0-9][0-9].txt/.txt}"
done
马克的回答涵盖了许多选项 但是,如果您想要递归的东西,我会使用基于
查找的解决方案,如下所示:
find -E . -regex '.*/[0-9]{13}\.txt' -exec \
sh -c 'set -; mv -v "$0" "${0%???.txt}.txt"' "{}" \;
注:
- 我使用的是FreeBSD,它有一个
-E
选项来告诉-regex
使用ERE。如果您使用的是较旧的操作系统,则可能需要将ERE转换为BRE
- ERE坚持使用13位数字。这就避免了anubhava担心如果你多次运行转换,会增加递减
- 对于参数扩展,我使用了
${..%..}
而不是${../../}
,使这个POSIX兼容而不是依赖于bash。(当然,它在bash中也可以工作,只是不需要。)
- 您可能想知道为什么匹配只删除单个通配符而不是数字。这很好-对我来说更容易键入,并且我们已经将文件名约束设置为
查找
选项的一部分
如果您希望避免使用find
,但仍然希望在bash中使用递归功能,则可以使用globstar
选项:
shopt -s globstar extglob
for f in **/+([0-9]).txt; do
[[ $f =~ ^[0-9]{13}\.txt$ ]] && mv -v "$f" "${f%...\.txt}.txt"
done
请注意,globstar
取决于bash版本4。OP只需运行一次,否则它还将1461758015.txt
重命名为1461758.txt
,然后1461758.txt
如果OP仍然使用bash,则将extglob与ls+([0-9]).txt一起重命名为,以及在非常大的目录中更高的性能。一种递归工作的故障保护python替代方案:
shopt -s globstar extglob
for f in **/+([0-9]).txt; do
[[ $f =~ ^[0-9]{13}\.txt$ ]] && mv -v "$f" "${f%...\.txt}.txt"
done