Linux 在Bash中使用带有find的基于Perl的重命名命令
今天我在玩Bash脚本时偶然发现了Perl。当我试图删除多个文件名中的空格时,我找到了post,这对我帮助很大 经过一番努力,我终于理解了rename和substitution命令及其语法。由于文件重复,我想尝试将文件名末尾的所有“x(x)”替换为“x”。但当我试图自己做的时候,它似乎不起作用。我有三个关于以下代码的问题:Linux 在Bash中使用带有find的基于Perl的重命名命令,linux,perl,bash,redirect,file-descriptor,Linux,Perl,Bash,Redirect,File Descriptor,今天我在玩Bash脚本时偶然发现了Perl。当我试图删除多个文件名中的空格时,我找到了post,这对我帮助很大 经过一番努力,我终于理解了rename和substitution命令及其语法。由于文件重复,我想尝试将文件名末尾的所有“x(x)”替换为“x”。但当我试图自己做的时候,它似乎不起作用。我有三个关于以下代码的问题: 为什么在我运行它时没有执行任何操作 我使用重定向将成功注释显示为错误,因此我知道发生了什么。我做错了什么 经过大量研究,我仍然不完全理解Bash中的文件描述符和重定向,以及
- 为什么在我运行它时没有执行任何操作
- 我使用重定向将成功注释显示为错误,因此我知道发生了什么。我做错了什么
- 经过大量研究,我仍然不完全理解Bash中的文件描述符和重定向,以及Perl中替代函数的语法。谁能给我一个好教程的链接
find -name "*_(*)." -type f | xargs rename 's/)././g'
find -name "*_(*." -type f | xargs rename 's/_(//g'
或:
在这两种情况下,文件名都添加到rename
的命令行中。实际上,rename
必须读取其标准输入才能发现文件名,但事实并非如此
第一个找到了你想要的文件吗?是否需要图案末尾的圆点?正则表达式是否实现了您的期望?好的,让我们也调试其中的一些
您可以使用更复杂的正则表达式在一个命令中完成这一切:
find . -name "*_(*)" -type f -exec rename 's/_\((\d+)\)$/$1/' {} +
find
模式被更正为丢失尾部
的要求。如果在扩展之前插入了(x)
,则需要“*(*).*
作为find
的模式(并且需要修改Perl正则表达式)
Perl替代品需要解剖:
\(
匹配一个开括号
(
启动捕获组
\d+
查找“一个或多个数字”
)
停止捕获组。它是第一个也是唯一一个,因此被赋予数字1
\)
匹配一个右括号
$
与文件名的结尾匹配
- 替换中的
$1
将捕获组1的值放入替换文本中
在您的代码中,2>&1
将第二个rename
命令中的错误消息发送到标准输出,而不是标准错误。这在这里真的没什么帮助
你需要两个单独的教程;您不会找到一个教程介绍Bash中的I/O重定向和Perl中的正则表达式
“官方”Perl正则表达式教程是:
- ,也可以在您的计算机上作为
perldoc perlretut
提供
Bash手册介绍了I/O重定向,但有些简洁:
谢谢,这真的让我很沮丧。但是我仍然不明白为什么在这个系统中没有使用xargs或exec。在这里,rename命令后跟正则表达式足以删除文件名中的空格。另外,我是否与exec或xargs合作有关系?其中一种解决方案是否更适合此目的?这取决于rename
或prename
命令的定义。有些版本可能每行读取一个文件名;我的版本(最初从《骆驼》的第一版中选取)就是这样做的。如果使用命令行参数调用,它将重命名这些参数;如果调用时没有命令行参数(regex除外),它将读取标准输入,在换行符上拆分,并将其作为文件处理。我的版本太粗心了,把所有的标准输入都弄糟了;如果处理千兆字节的文件名,这是次优的。
find -name "*_(*)." -type f -exec rename 's/)././g' {} +
find -name "*_(*." -type f -exec rename 's/_(//g' {} +
find . -name "*_(*)" -type f -exec rename 's/_\((\d+)\)$/$1/' {} +