替换OSX中文件名BASH并发症中的单词

时间:2015-10-30 16:45:33

标签: macos bash sed

我在我的问题中找到了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?

如何修改上面的代码才能正常使用?

4 个答案:

答案 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,这不会递归到目录中。