Ubuntu 12.04 中的命令rename
(手册页说它是 perl v5.14.2 2012-03-23 的一部分)在单个目录中运行良好,但我想在子目录中使用它(或者,更一般地说,在作为另一个命令的输出的文件列表上,通过反引号)。例如,我希望
rename "s/ /-/g" `find .`
将当前目录下所有文件名中的所有空格更改为破折号。但此命令不执行任何操作。
(编辑:更改rename -n
为rename
。该选项适合安全实验,但在这里只会分散注意力。)
反引号没有问题,因为find .
用 eg替换echo */*
就可以了。
首先执行find . > foo
,然后find .
用替换cat foo
,什么也不做。
即使将文件列表折叠成一行,用 替换find .
,find . | tr -d '\n'
也无济于事。
哪个元素有问题?
答案1
这不会起作用:
rename 's/ /-/g' `find .`
运行 find 命令后,shell 会对结果进行分词。因此,没有带空格的文件名能够完整保留下来:它被分成了几个部分。
您可以使用以下方法避免这种情况:
rename 's/ /-/g' */*
在这种命令形式下,shell 不会进行分词,您的命令rename
将会成功。这种形式甚至适用于包含空格、制表符或任何其他困难字符的文件名。
或者,使用 find -exec
:
find . -name '* *' -exec rename 's/ /-/g' {} +
此形式适用于包含空格、制表符或任何其他困难字符的文件名。
示范
为了查看哪里出了问题,让我们创建一个包含空格的文件
$ touch "a b c"
$ find .
.
./a b c
为了弄清楚发生了什么,让我们创建一个函数,将它看到的每个参数放在双引号内并显示它:
$ display() { printf '"%s"\n' "$@"; }
现在,我们可以用来display
查看运行时发生的情况find .
:
$ display `find .`
"."
"./a"
"b"
"c"
这显示了单词拆分的实际效果。文件名a b c
被拆分为三个独立的单词。