递归删除文件名中的换行符

递归删除文件名中的换行符

正如标题所示,我想扫描一个目录和所有子目录,并从文件名中删除所有换行符。

此处提出的当前解决方案不起作用:删除文件名中的换行符

这是我使用时得到的结果:

$ find -name $'*\n*' -exec rename $'s|\n| |g' '{}' \; 
rename: not enough arguments 
Try 'rename --help' for more information.

如果我添加一个*

$ find -name $'*\n*' -exec rename $'s|\n| |g' '{}' * \;

这不会产生任何错误消息(仅接受命令),但不会重命名子目录中的文件

答案1

确保您使用perl基于 - 的rename变体之一(有时称为 )prename,而不是来自util-linux(有时称为rename.ul)的变体。

from 的util-linux限制要大得多(尽管更新得多),使用不同的语法,只能替换固定字符串,并且不能替换字符串的所有出现位置。

在这里,我将使用 perlrename变体,确保仅转换文件名中的换行符,而不是导致它们的目录组件,并用于-depth处理分支之前的叶子。

perl识别\n为换行符,因此您不需要使用$'...'其代码参数(尽管如果您的做法与我最初的想法相反也没关系)。

find . -depth -name $'*\n*' -exec rename '
  s{[^/]*\z}{$& =~ y/\n/ /r}e' '{}' +

或者如果可用的话使用(尽管这将在每个包含其中文件的目录中-execdir至少运行一个):rename\n

find . -depth -name $'*\n*' -execdir rename 'y/\n/ /' {} +

或者你可以使用zsh's zmv

autoload zmv
NL=$'\n'
zmv "(**/)(*$NL*)(#qD)" '$1${2//$NL/ }'

(与基于find- 的方法相反,即使文件名包含不形成有效字符的字节序列,它仍然有效。如果检测到冲突,它也将退出而不执行任何操作)。

答案2

rename提供的命令的用法util-linux与您链接的答案中给出的命令不同。特别是,它需要一个单独的fromandto参数,而不是单个 sed 样式的替换命令 - 因此会出现错误消息not enough arguments

SYNOPSIS
       rename [options] expression replacement file...

所以在这种情况下你需要

find . -name $'*\n*' -exec rename $'\n' ' ' {} \;

也可以看看:

并进行简单的使用比较

相关内容