正如标题所示,我想扫描一个目录和所有子目录,并从文件名中删除所有换行符。
此处提出的当前解决方案不起作用:删除文件名中的换行符
这是我使用时得到的结果:
$ 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
与您链接的答案中给出的命令不同。特别是,它需要一个单独的from
andto
参数,而不是单个 sed 样式的替换命令 - 因此会出现错误消息not enough arguments
。
SYNOPSIS
rename [options] expression replacement file...
所以在这种情况下你需要
find . -name $'*\n*' -exec rename $'\n' ' ' {} \;
也可以看看:
并进行简单的使用比较