使用find和sed递归重命名文件
我想通过一堆目录,并重命名以_test.rb结尾的所有文件,而不是以_spec.rb结尾。 这是我从来没有想过如何处理bash的事情,所以这次我想我会努力让它钉上。 尽管我到目前为止只是想尽一点办法,但我的最大努力是:
find spec -name "*_test.rb" -exec echo mv {} `echo {} | sed s/test/spec/` ;
注意:在exec之后有一个额外的回显,以便在测试它时打印命令而不是运行。
当我运行它时,每个匹配的文件名的输出是:
mv original original
即sed的替代已经丢失。 有什么诀窍?
发生这种情况是因为sed
收到字符串{}
作为输入,可以通过以下方式进行验证:
find . -exec echo `echo "{}" | sed 's/./foo/g'` ;
它以递归方式为目录中的每个文件打印foofoo
。 这种行为的原因是管道在扩展整个命令时由shell执行一次。
没有办法以这种方式引用sed
管道, find
会为每个文件执行它,因为find
不会通过shell执行命令,也没有管道或反引号的概念。 GNU findutils手册解释了如何通过将管道放入单独的shell脚本来执行类似的任务:
#!/bin/sh
echo "$1" | sed 's/_test.rb$/_spec.rb/'
(可能有一些不正当的方法使用sh -c
和一大堆引用来完成所有这些命令,但我不会去尝试。)
以最接近原始问题的方式解决它可能会使用xargs“每命令行参数”选项:
find . -name *_test.rb | sed -e "p;s/test/spec/" | xargs -n2 mv
它会递归地查找当前工作目录中的文件,回显原始文件名( p
),然后修改名称( s/test/spec/
),并将它们全部成对( xargs -n2
)输入到mv
。 请注意,在这种情况下,路径本身不应包含字符串test
。
你可能想要考虑其他方式
for file in $(find . -name "*_test.rb")
do
echo mv $file `echo $file | sed s/_test.rb$/_spec.rb/`
done
链接地址: http://www.djcxy.com/p/78329.html
上一篇: Recursively rename files using find and sed
下一篇: How to copy a file to multiple directories using the gnu cp command