查找并用 '.' 替换最后一个字符 '_' 在文件名上递归

Jos*_*lva 4 centos shell-script

我有数百万个文件以“已损坏”的名称保存。扩展名已保存为_pdf.

我想要的是递归地编辑所有这些扩展以按预期使用点。

find . -name '*_pdf' -type f -exec bash -c 'mv -- "$1" "${1//_/.}"' -- {} \;
Run Code Online (Sandbox Code Playgroud)

我已经尝试过使用这个 bash 脚本,但它替换了所有以 '.' 建立的 '_',我只想要最后一个 _ 并且如果使用通用扩展名(pdf、jpg、jpeg)。

ste*_*ver 13

它正在替换_因为${1//_/.}是全局的所有实例(${1/_/.}将是非全局的,但替换第一个匹配项而不是最后一个匹配项)。

相反,您可以使用 POSIX${1%_*}${1##*_}删除最短后缀和最长前缀,然后重新加入它们:

find . -name '*_pdf' -type f -exec sh -c 'mv "$1" "${1%_*}.${1##*_}"' sh {} \;
Run Code Online (Sandbox Code Playgroud)

或者

find . -name '*_pdf' -type f -exec sh -c 'for f do mv "$f" "${f%_*}.${f##*_}"; done' sh {} +
Run Code Online (Sandbox Code Playgroud)

对于多个扩展:

find . \( -name '*_pdf' -o -name '*_jpg' -o -name '*_jpeg' \) -type f -exec sh -c '
  for f do mv "$f" "${f%_*}.${f##*_}"; done
' sh {} +
Run Code Online (Sandbox Code Playgroud)

我删除了--选项结尾的分隔符 - 这里应该没有必要,因为find名称前缀为./.

您可能需要增加一个-i选项mv,如果有可能,即一个file_pdffile.pdf存在于给定的目录,你要得到一个机会,不揍了exising file.pdf


pLu*_*umo 7

使用 perlrename工具:

find ... rename 's/_pdf$/.pdf/' {} +
Run Code Online (Sandbox Code Playgroud)

您可以为不同的扩展单独运行,或者一次替换多个“通用扩展”:

find ... rename 's/_(pdf|jpg|jpeg)$/.\1/' {} +
Run Code Online (Sandbox Code Playgroud)

如果您没有 perl 重命名,则可以使用其他rename工具

find ... rename '_pdf' '.pdf' {} +
Run Code Online (Sandbox Code Playgroud)