ops*_*psb 80 bash scripting replace sed find
我想浏览一堆目录并将所有以_test.rb结尾的文件重命名为_spec.rb结尾.这是我从未想过如何处理bash的事情所以这次我认为我会付出一些努力来实现它.到目前为止,我做得很短,我最大的努力是:
find spec -name "*_test.rb" -exec echo mv {} `echo {} | sed s/test/spec/` \;
Run Code Online (Sandbox Code Playgroud)
注意:在exec之后有一个额外的回声,所以在我测试时打印命令而不是运行.
当我运行它时,每个匹配文件名的输出是:
mv original original
Run Code Online (Sandbox Code Playgroud)
即sed的替换已经丢失.有什么诀窍?
ram*_*tam 116
要以最接近原始问题的方式解决它可能会使用xargs"args per command line"选项:
find . -name *_test.rb | sed -e "p;s/test/spec/" | xargs -n2 mv
Run Code Online (Sandbox Code Playgroud)
它以递归方式查找当前工作目录中的文件,回显原始文件名(p),然后是修改后的名称(s/test/spec/),并将其全部输入到mv成对(xargs -n2)中.请注意,在这种情况下,路径本身不应包含字符串test.
Fre*_*Foo 32
发生这种情况是因为sed接收字符串{}作为输入,可以通过以下方式验证:
find . -exec echo `echo "{}" | sed 's/./foo/g'` \;
Run Code Online (Sandbox Code Playgroud)
它foofoo以递归方式打印目录中的每个文件.这种行为的原因是,当它扩展整个命令时,shell会执行一次管道.
没有办法sed以这样的方式引用管道,find它将为每个文件执行它,因为find不通过shell执行命令,并且没有管道或反引号的概念.GNU findutils手册解释了如何通过将管道放在单独的shell脚本中来执行类似的任务:
#!/bin/sh
echo "$1" | sed 's/_test.rb$/_spec.rb/'
Run Code Online (Sandbox Code Playgroud)
(sh -c在一个命令中可能有一些不正常的使用方法和大量的引号来完成所有这些,但我不打算尝试.)
ajr*_*eal 23
你可能想要考虑其他方式
for file in $(find . -name "*_test.rb")
do
echo mv $file `echo $file | sed s/_test.rb$/_spec.rb/`
done
Run Code Online (Sandbox Code Playgroud)
csg*_*csg 17
我发现这个更短
find . -name '*_test.rb' -exec bash -c 'echo mv $0 ${0/test.rb/spec.rb}' {} \;
Run Code Online (Sandbox Code Playgroud)
如果你愿意,你可以在没有sed的情况下完成:
for i in `find -name '*_test.rb'` ; do mv $i ${i%%_test.rb}_spec.rb ; done
Run Code Online (Sandbox Code Playgroud)
${var%%suffix}剥离suffix的价值var.
或者,使用sed来做:
for i in `find -name '*_test.rb'` ; do mv $i `echo $i | sed 's/test/spec/'` ; done
Run Code Online (Sandbox Code Playgroud)
你提到你正在使用bash你的shell,在这种情况下你实际上并不需要find并sed实现批量重命名你之后......
假设您使用的bash是shell:
$ echo $SHELL
/bin/bash
$ _
Run Code Online (Sandbox Code Playgroud)
...并假设您已启用所谓的globstarshell选项:
$ shopt -p globstar
shopt -s globstar
$ _
Run Code Online (Sandbox Code Playgroud)
...最后假设您已经安装了该rename实用程序(在util-linux-ng包中找到)
$ which rename
/usr/bin/rename
$ _
Run Code Online (Sandbox Code Playgroud)
...然后你可以在bash one-liner中实现批量重命名,如下所示:
$ rename _test _spec **/*_test.rb
Run Code Online (Sandbox Code Playgroud)
(globstarshell选项将确保bash找到所有匹配的*_test.rb文件,无论它们嵌套在目录层次结构中有多深......用于help shopt了解如何设置选项)
最简单的方法:
find . -name "*_test.rb" | xargs rename s/_test/_spec/
Run Code Online (Sandbox Code Playgroud)
最快的方法(假设您有4个处理器):
find . -name "*_test.rb" | xargs -P 4 rename s/_test/_spec/
Run Code Online (Sandbox Code Playgroud)
如果要处理大量文件,则通过管道传输到xargs的文件名列表可能会导致生成的命令行超过允许的最大长度.
您可以使用检查系统的限制 getconf ARG_MAX
在大多数Linux系统上,您可以使用free -b或cat /proc/meminfo查找您需要使用多少RAM; 否则,请使用top或您的系统活动监控应用程序.
一种更安全的方式(假设您有1000000字节的ram可以使用):
find . -name "*_test.rb" | xargs -s 1000000 rename s/_test/_spec/
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
79699 次 |
| 最近记录: |