Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex Bash正则表达式重命名文件_Regex_Bash_Rename - Fatal编程技术网

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之间,它一次

我有一堆文件,只是一个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
之间,它一次查看一个文件,当前文件的名称位于参数
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