是否存在与shell无关的等效Bash子串替换:
foo=Hello
echo ${foo/o/a} # will output "Hella"
大多数情况下,我可以使用bash
,因此这不是问题,但是当与find -exec
结合使用时,它不起作用。例如,要将所有.cpp
个文件重命名为.c
,我想使用:
# does not work
find . -name '*.cpp' -exec mv {} {/.cpp$/.c}
目前,我正在使用:
# does work, but longer
while read file; do
mv "$file" "${file/.cpp$/.c}";
done <<< $(find . -name '*.cpp')
理想情况下,可以在脚本中使用的解决方案更好!
答案 0 :(得分:4)
使用find
和-exec
可以执行此操作:
find . -name '*.cpp' -exec bash -c 'f="$1"; mv "$f" "${f/.cpp/.c}"' - '{}' \;
但是,这会为每个文件名分叉bash -c
,因此使用xargs
或for
这样的循环更好,因为性能原因:
while IFS= read -d '' -r file; do
mv "$file" "${file/.cpp/.c}"
done < <(find . -name '*.cpp' -print0)
答案 1 :(得分:1)
顺便说一下,使用bash
的替代方法是使用rename
。如果您拥有rename
命令的 cool 版本,该命令随perl
一起提供,您可以执行以下操作:
find -name '*.cpp' -exec rename 's/\.cpp$/.c/' {} +
上面的示例假设您拥有GNU findutils
,因此您不需要传递当前目录,因为它是默认值。如果您没有GNU findutils
,则需要明确传递它:
find . -name '*.cpp' -exec rename 's/\.cpp$/.c/' {} +