我有一堆只是一个unix时间的文件。问题是他们的文件名是millis,扫描目录的程序希望他们在几秒钟内完成。所以我需要重命名所有文件,以删除.txt扩展名前的最后3位数字。 IE:Bash Regex重命名文件
1461758015598.txt - > 1461758015.txt
我是新来的正则表达式和bash,所以我不知道如何做到这一点。
我有一堆只是一个unix时间的文件。问题是他们的文件名是millis,扫描目录的程序希望他们在几秒钟内完成。所以我需要重命名所有文件,以删除.txt扩展名前的最后3位数字。 IE:Bash Regex重命名文件
1461758015598.txt - > 1461758015.txt
我是新来的正则表达式和bash,所以我不知道如何做到这一点。
这里有一种方法:
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
所以,你可能需要使用外部工具,使其更为紧凑(假设有目录中没有空格或换行符的任何文件名):
for f in $(ls -1 | egrep '^[0-9]{13}\.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
基础的解决方案是这样走:
find -E . -regex '.*/[0-9]{13}\.txt' -exec \
sh -c 'set -; mv -v "$0" "${0%???.txt}.txt"' "{}" \;
注:
-E
选项告诉-regex
使用ERE。如果您使用的是较旧的操作系统,则可能需要将ERE转换为BRE。${..%..}
而不是${../../}
,这使得此POSIX兼容,而不是依赖于bash。 (它当然也会在bash中工作,但它并不需要)find
的选项的一部分。如果您更愿意避免使用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
一故障保护python的替代工作递归:http://stackoverflow.com/a/39698169/191246 – ccpizza