简单方法
find + perl + xargs + mv
xargs -n2
可以每行打印两个参数。当与 Perl 的 print $_
结合使用时(用于先打印 $STDIN),它成为一个强大的重命名工具。
find . -type f | perl -pe 'print $_; s/input/output/' | xargs -d "\n" -n2 mv
perl -pe 'print $_; s/OldName/NewName/' | xargs -n2
的结果如下:
OldName1.ext NewName1.ext
OldName2.ext NewName2.ext
OldName3.ext NewName3.ext
OldName4.ext NewName4.ext
我在我的系统上没有Perl的
rename
命令可用。
如何工作?
1.
find . -type f
输出文件路径(或文件名...您可以通过正则表达式控制要处理的内容!)
2.
-p
打印通过正则表达式处理的文件路径,
-e
执行内联脚本
3.
print $_
首先打印原始文件名(与
-p
无关)
4.
-d "\n"
按换行符切割输入,而不是默认的空格字符
5.
-n2
每行打印两个元素
6.
mv
获取前一行的输入内容
高级方法
这是我首选的方法,因为它非常可靠。高级部分是在管道中的每个可执行文件的标准输出中使用空字节,并在后续可执行文件的标准输入中处理它们的复杂性增加。为什么要这样做?:这样可以避免文件名中的空格和换行符引起的问题。
假设我想将所有的“.txt”文件重命名为“.md”文件:
find . -type f -printf '%P\0' | perl -0 -l0 -pe 'print $_; s/(.*)\.txt/$1\.md/' | xargs -0 -n 2 mv
这里的魔法在于管道中的每个过程都支持空字节(0x00)作为分隔符,而不是空格或换行符。前面提到的第一种方法使用换行符作为分隔符。请注意,我尝试轻松支持
find .
而不使用子进程。在这里要小心(你可能想在运行正则表达式匹配或更糟的是破坏性命令如
mv
之前检查
find
的输出)。
工作原理(仅包括上述更改):
- 在
find
中:使用-printf '%P\0'
仅打印文件名而不包括路径,后跟空字节。根据您的用例进行调整,无论是匹配文件名还是整个路径。
- 在
perl
和xargs
中:使用-0
将标准输入的分隔符设置为空字节(而不是空格)
- 在
perl
中:使用-l0
将标准输出的分隔符设置为空字节(八进制000)