uve*_*ett 5 bash quotes asterisk expansion
在目录~/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
Run Code Online (Sandbox Code Playgroud)
(该cp命令无法将最后foo一个"foo foo"视为同一目录名的一部分.)
for dir in `find . -type d -name '*foo'` ; do cp "$dir/*" "$(echo $dir|sed 's_foo__g')" ; done
Run Code Online (Sandbox Code Playgroud)
("$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)
Run Code Online (Sandbox Code Playgroud)
使用-print0(find和IFS= read -r -d '') 可确保带有换行符的文件名不会让您感到困惑。
使用该< <(...)构造可确保如果循环内部设置变量、更改目录状态或执行类似操作,这些更改将保留下来(管道的右侧位于 bash 中的子 shell 中,因此管道进入 while 循环将意味着在 while 循环内对 shell 状态所做的任何更改都将在退出时被丢弃)。
使用${dir/foo/}比调用 效率高得多sed,因为它在 bash 内部进行字符串替换。