Bash:递归重命名文件的一部分

13 浏览
0 Comments

Bash:递归重命名文件的一部分

我想遍历一系列目录,将所有以_test.rb结尾的文件重命名为以_spec.rb结尾的文件。这是我从未完全掌握如何使用bash完成的事情,所以这次我打算花些功夫来解决它。然而,目前我还没有找到解决方法,我最好的尝试是:\n

find spec -name "*_test.rb" -exec echo mv {} `echo {} | sed s/test/spec/` \;

\n注意:在exec之后有一个额外的echo,这样在我测试时会打印出命令而不是运行它。\n当我运行它时,每个匹配的文件名的输出是:\n

mv original original

\n即sed的替换已经丢失了。有什么诀窍吗?

0
0 Comments

问题的原因:需要批量递归地将文件名中的"_test.rb"替换为"_spec.rb"。

解决方法:使用Bash命令递归地重命名文件名中的一部分。

具体的解决方法如下:

for file in $(find . -name "*_test.rb")
do 
  echo mv $file `echo $file | sed s/_test.rb$/_spec.rb/`
done

这是一个简单的循环命令,通过查找所有文件名为"\*_test.rb"的文件,并将其重命名为"\*_spec.rb"。

另外,还可以将上述命令改写为单行命令,如下:

for file in $(find . -name "*_test.rb"); do echo mv $file `echo $file | sed s/_test.rb$/_spec.rb/`; done

需要注意的是,如果文件名中包含空格,则上述命令将无法正常工作。可以通过设置for循环仅在换行符上分割文件名来解决这个问题。可以参考cyberciti.biz/tips/handling-filenames-with-spaces-in-bash.html中的示例来实现。

另外,也可以使用find命令的-exec选项来进行重命名操作,如下:

find . -name "*_test.rb" -exec bash -c 'mv "$0" "${0/_test.rb/_spec.rb}"' {} \;

以上就是解决在Bash中递归地重命名文件名的问题的方法。

0
0 Comments

在Bash中递归重命名文件的一部分,出现问题的原因是sed接收到输入的字符串{},可以通过以下命令进行验证:

find . -exec echo `echo "{}" | sed 's/./foo/g'` \;

该命令会递归地为目录中的每个文件打印foofoo。这种行为的原因是整个命令在shell扩展时由shell执行一次。

没有办法以一种引用sed管道的方式来执行find,使其对每个文件执行一次命令,因为find不通过shell执行命令,也没有管道或反引号的概念。GNU findutils手册解释了如何通过将管道放在单独的shell脚本中来执行类似的任务:

#!/bin/sh
echo "$1" | sed 's/_test.rb$/_spec.rb/'

(也许有一些古怪的使用sh -c和大量引号的方式可以在一个命令中完成所有这些,但我不会尝试。)

对于那些好奇在这里使用sh -c的古怪用法,以下是示例代码:find spec -name "*_test.rb" -exec sh -c 'echo mv "$1" "$(echo "$1" | sed s/test.rb\$/spec.rb/)"' _ {} \;

这个下划线是什么?很棒的解决方案-但我更喜欢ramtam的答案:)

谢谢!节省了我很多麻烦。为了完整起见,这是我将其管道化到脚本的方法:find . -name "file" -exec sh /path/to/script.sh {} \;

0
0 Comments

Bash: 递归重命名文件中的一部分

在处理文件名时,有时候需要递归地重命名文件中的一部分。下面是一个解决方案,可以通过使用xargs的"args per command line"选项来实现。

find . -name "*_test.rb" | sed -e "p;s/test/spec/" | xargs -n2 mv

这段代码会递归地在当前工作目录中查找文件,然后将原始文件名(p)和修改后的文件名(s/test/spec/)输出,并以一对一对的方式传递给mv命令(xargs -n2)。需要注意的是,路径本身不应该包含字符串test

不幸的是,这种方法存在空格的问题。如果文件夹名中包含空格,会导致xargs命令出错(可以通过使用-p选项来确认是否出错,进入交互模式)。

这正是我所需要的。可惜存在空格的问题(虽然我没有进行测试)。但对于我目前的需求来说,它是完美的。我建议先使用"echo"而不是"mv"作为"xargs"参数进行测试。

如果你需要处理路径中的空格,并且你使用的是GNU sed >= 4.2.2,那么你可以使用-z选项,结合find的-print0和xargs的-0选项:

find -name '*._test.rb' -print0 | sed -ze "p;s/test/spec/" | xargs -0 -n2 mv

这是最佳解决方案。比使用find -exec要快得多。谢谢你。

如果路径中有多个test文件夹,则这种方法不起作用。sed只会重命名第一个文件夹,mv命令会因为找不到文件或目录而报错。

0