繁体   English   中英

双引号与Bash中的星号文件名扩展

[英]Double quotes vs asterisk filename expansion in Bash

在目录~/temp/a/foo/~/temp/b/foo foo/我有一些名为bar1bar2bar bar1bar bar2等的文件。

我正在尝试编写一行Bash,将包含“foo”的目录中的所有这些文件作为名称的最后一部分复制到相应“foo”文件夹上方的文件夹中。

只要文件名中没有空格,这是一项简单的任务,但在处理foo foo目录时,以下两个命令会失败:

for dir in `find . -type d -name '*foo'` ; do cp $dir/* "$(echo $dir|sed 's_foo__g')" ; done

cp命令无法将"foo foo"的最后一个foo视为同一目录名的一部分。)

for dir in `find . -type d -name '*foo'` ; do cp "$dir/*" "$(echo $dir|sed 's_foo__g')" ; done

"$dir/*"未展开。)

尝试将$dir/*替换$dir/* "$(echo $dir/*)"尝试更不成功。

是否有一种简单的方法来扩展$dir/*以便cp理解?

for循环不仅错误 - sed也不适合这项工作。

while IFS= read -r -d '' dir; do
  cp "$dir" "${dir/foo/}"
done < <(find . -type d -name '*foo' -print0)

find (和IFS= read -r -d '' )上使用-print0可确保带有换行符的文件名不会弄乱你。

使用< <(...)构造确保如果循环内部设置变量,更改目录状态或执行类似的操作,那些更改将继续存在(管道的右侧位于bash的子shell中,如此管道进入while循环意味着在while循环中对shell的状态所做的任何更改都将在其退出时被丢弃。

使用${dir/foo/}比调用sed更有效,因为它在bash内部执行字符串替换。

这里的问题是不是与cp ,而是for ,因为默认情况下它被分割的话你的输出壳层的,而不是由目录名。

一个懒惰的解决方法是使用while而是逐行处理目录列表,如下所示:

find . -type d -name '*foo' | while read dir; do cp "$dir"/* "$(echo $dir | sed 's_foo__g')" ; done

这应该可以解决你的空间问题,但这绝不是一个万无一失的解决方案。

请参阅Charles Duffy的答案,以获得更准确的解决方案。

~/temp/b/foo foo/重命名为没有空格的东西,例如~/temp/b/foo_foo/并做你想要再做的事情。 之后,如果你真的需要,你可以将它重命名为原始空间。 BTW。 我自己从不使用包含空格的文件名,只是为了避免像你现在面临的那样复杂化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM