在目录 ~/temp/a/foo/
和 ~/temp/b/foo foo/
我有一些名为 bar1
、bar2
、bar bar1
、bar 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/*
替换为 "$(echo $dir/*)"
的尝试甚至不太成功。
有没有一种简单的方法来扩展 $dir/*
以便 cp
理解?
最佳答案
不仅是for
循环错误 -- sed
也不是这项工作的正确工具。
while IFS= read -r -d '' dir; do
cp "$dir" "${dir/foo/}"
done < <(find . -type d -name '*foo' -print0)
使用 -print0
在 find
上(和 IFS= read -r -d ''
)确保带有换行符的文件名不会让您感到困惑。
使用 < <(...)
construct 确保如果循环内部设置变量、更改目录状态或做类似的事情,这些更改将继续存在(管道的右侧在 bash 的子 shell 中,因此管道进入 while 循环意味着否则,在 while 循环中对 shell 状态所做的任何更改都将在其退出时被丢弃。
使用 ${dir/foo/}
比调用 sed
效率高得多,因为它在 bash 内部进行字符串替换。
关于bash - Bash 中的双引号与 Asterisk 文件名扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15455780/