Linux 在Bash中使用带有find的基于Perl的重命名命令

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。当我试图删除多个文件名中的空格时,我找到了post,这对我帮助很大

经过一番努力,我终于理解了rename和substitution命令及其语法。由于文件重复,我想尝试将文件名末尾的所有“x(x)”替换为“x”。但当我试图自己做的时候,它似乎不起作用。我有三个关于以下代码的问题:

  • 为什么在我运行它时没有执行任何操作
  • 我使用重定向将成功注释显示为错误,因此我知道发生了什么。我做错了什么
  • 经过大量研究,我仍然不完全理解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/' {} +