我尝试运行以下命令:
find . -type f -exec rename -v 's/ /_/g' {} \;
,以递归方式重命名所有文件,名称中包含空格和下划线。问题是它有时有效,有时无效。当它不起作用时,我收到以下错误:
Can't rename ./dir/subdir/file name with spaces ./dir/subdir/file_name_with_spaces: No such file or directory
我可能做错了什么吗?
答案1
发生的情况是您尝试rename
在以下文件上运行目录名称中带有空格。默认情况下,该rename
实用程序有点简单化,它将给定的 Perl 代码位应用于完整的参数,即完整的路径名,而不仅仅是路径名的文件名部分。
幸运的是,很容易将操作限制为路径名的文件名部分:
find . -type f -execdir rename -v 'tr/ /_/' -- {} \;
该-execdir
谓词是非标准的,但普遍实现。使用-execdir
in 代替-exec
,这会使用找到文件的目录作为当前目录来执行命令。这样,rename
实用程序永远看不到文件的父目录的名称。
我在这里使用--
它来防止我们尝试重命名名称以破折号开头的文件的事件(请参阅“--”(双破折号)是什么意思?)。这对于 GNU 来说不是问题,find
因为文件名将以 为前缀,但至少在 BSD 系统./
的某些实现上不会发生这种情况。find
另一种选择是使用该rename
实用程序的-d
、--filename
、--nopath
或--nofullpath
选项(这些都是相同的):
find . -type f -exec rename -d -v 'tr/ /_/' {} +
这会阻止实用程序考虑任何给定路径名参数的文件名部分以外的任何内容。
我冒昧地将 Perl 表达式从一个s///
命令更改为一个tr///
命令,因为我们正在执行的转换是一个简单的音译,而不是通用替换。
您可能还希望仅对rename
包含空格的文件名运行。-name '* *'
在-exec
或之前通过测试选出这些-execdir
。