我在我的问题中找到了answer,该问题使用以下代码使用sed
从文件名中删除单词:
for fyle in $(find . -name "*.*")
do
mv -i $fyle `echo $fyle | sed -e 's/FOO//gI' -e 's/BANG//gI' `
done
但是在我的mac上它会阻塞路径有空格的文件名。
我尝试使用双引号修复它,但无法使其工作:变量fyle现在包含整个文件列表,而不是一次一个。
因为原始海报似乎对代码感到满意,也许我的问题是因为我的OSX风格的bash?
如何修改上面的代码才能正常使用?
答案 0 :(得分:4)
您不应在find
循环中迭代for
命令的输出,否则将发生包含空格/换行符的文件名的shell扩展,并且您的结果将是错误的。
在-print0
中使用find
选项,并使用while read
循环中的流程替换进行迭代,并使用空IFS
。
while IFS= read -rd '' fyle; do
mv -i "$fyle" $(sed 's/FOO//gI; s/BANG//gI' <<< "$fyle")
done < <(find . -type f -name "*.*")
答案 1 :(得分:4)
正如其他人所说,quotes are your friends.
但是既然你正在使用bash,那么 使用参数扩展可以使用这样的东西:
find . -name '*.*' -exec bash -c 'out="${1//FOO/}; out="${out//BANG/}; mv -v "$1" "$out"' -- {} \;
但在这种情况下,即使find
也是不必要的,所以你可以完全避免使用子句:
shopt -s globstar
for f in **/*FOO*.* **/*BANG*.*; do
out=${f//FOO/}
out=${out//BANG/}
mv -v "$f" "$out"
done
这当然假设您要搜索的关键字位于文件名中的一个点之前。它还假设您正在为globstar
运行bash v4。
答案 2 :(得分:2)
我认为您需要在mv
命令中对引用变量引用进行双引号以说明空格...
mv -i "$fyle" ...
答案 3 :(得分:0)
这看起来很复杂。这会有用吗?使用Bash的内置字符串替换和文件通配来将bar
替换为baz
:
for i in *.txt; do mv "$i" "${i/bar/baz}"; done
这是在行动:
mike ~/foobar $ touch "foo bar baz.txt"
mike ~/foobar $ touch "foobar.txt"
mike ~/foobar $ touch "carbar.txt"
mike ~/foobar $ for i in *.txt; do mv "$i" "${i/bar/baz}"; done
mike ~/foobar $ ls
carbaz.txt foo baz baz.txt foobaz.txt
mike ~/foobar $
作为下面提到的chepner,这不会递归到目录中。