【问题标题】:Recurse through subdirectories and rename all files of a given extension the same filename [duplicate]递归子目录并将给定扩展名的所有文件重命名为相同的文件名[重复]
【发布时间】:2021-03-02 00:14:40
【问题描述】:

这应该很简单,但我在某个地方卡住了。

我想通过一个目录递归并将所有 pdf 重命名为相同的文件名。重命名的文件应保留在其当前子目录中。

当前的 PDF 文件名是任意的。

假设我从顶层目录运行这个脚本。在这个顶级目录中有几个子目录,每个子目录都有一个带有任意文件名的 PDF。

这可以重命名文件:

find . -iname "*.pdf" -exec rename 's/test.pdf/commonname.pdf/' '{}' \;

但由于当前文件名是任意的,我需要用正则表达式替换“任何字符或数字”来代替 test.pdf

我的理解是正确的正则表达式是.*

所以我尝试了:

find . -iname "*.pdf" -exec rename 's/.*/commonname.pdf/' '{}' \;

当我运行它时,第一个 PDF 被重命名为 commonpdf.pdf,但它被移到了顶层目录。我的用例要求 PDF 就地重命名。

我在这里遗漏了一些明显的东西,很明显 - 你能发现我的错误吗?

【问题讨论】:

  • find . -iname "*.pdf" -execdir mv \{\} commonname.pdf \; ?
  • 查看-exec echo {} \; 的输出——您会看到{} 包含完整路径,如/path/to/file.pdf,而.* 则替换包括路径在内的所有内容,而不仅仅是文件名。如果你有 GNU find,@Shawn 的方法是一个很好的解决方案:-execdir 将工作目录设置为包含匹配文件的目录。

标签: bash rename


【解决方案1】:

问题是在s/.*/commonname.pdf/ 中,.* 匹配完整路径,而不仅仅是文件名。您可以通过匹配非斜杠来确保正则表达式只适用于文件名:

find . -iname '*.pdf' -exec rename 's|[^/]*$|commonname.pdf|' '{}' \;

或者您可以使用 GNU find 的 -execdir,它将工作目录设置为包含匹配文件的目录:

find . -iname '*.pdf' -execdir rename 's/.*/commonname.pdf/' '{}' \;

或者根本不使用rename

find . -iname '*.pdf' -execdir mv {} commonname.pdf \;

或者不使用find,而是一次调用rename

rename 's|[^/]*$|commonname.pdf|' **/*.pdf

这需要globstar shell 选项来启用** glob。

使用-n 选项到rename 进行试运行而不实际更改文件名。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-07
    • 1970-01-01
    • 2021-02-28
    • 2016-01-31
    相关资源
    最近更新 更多