这工作正常:
$ eval 'echo "1" > ~/Desktop/in/foo'
但不是这个:
$ while IFS= read _cmd; do eval "$_cmd"; done < <(cat << EOF
'echo "1" > ~/Desktop/in/foo'
'echo "2" > ~/Desktop/in/bar'
EOF
)
bash: echo "1" > ~/Desktop/in/foo: No such file or directory
bash: echo "2" > ~/Desktop/in/bar: No such file or directory
如何修复它?
更新
正如所建议的,删除单引号是可行的,但不适用于此变体(仅用单引号引起来的文件名也是如此):
$ while IFS= read _cmd; do eval "$_cmd"; done < <(cat << EOF
echo "1" > ~/Desktop/in/foo (bis)
echo "2" > ~/Desktop/in/bar
EOF
)
连同提供的解决方案:
"$SHELL" << EOF
echo "1" > ~/Desktop/in/'foo (bis)'
echo "2" > ~/Desktop/in/bar
EOF
答案1
当您运行 时eval 'echo "1" > ~/Desktop/in/foo'
,shell 会删除单引号,然后eval
计算echo "1" > ~/Desktop/in/foo
。
当您运行eval "$_cmd"
(在更新前的代码中)时,shell 会展开$_cmd
并删除双引号,然后eval
计算'echo "1" > ~/Desktop/in/foo'
.请注意单引号。您不想eval
看到它们,请将它们从此处的文档中删除。
在更新后的代码中,您可能想要eval
评估echo "1" > ~/Desktop/in/'foo (bis)'
,因此请使用此处文档中的这一行。
嗯,“精确”一般来说并不是正确的词。一般来说<< EOF
(与 例如 相对<< 'EOF'
)扩展了此处文档中的变量和其他一些内容(您的示例中没有,但一般来说这就是它的工作原理)。那么IFS= read _cmd
不是IFS= read -r _cmd
。最后eval
得到一个字符串,不一定是精确的你使用的字符串。
逐行评估使得评估多行命令变得不可能。
除非您真的想依赖您提供的字符串<< EOF
并IFS= read
对其执行什么操作(并且您知道自己在做什么),否则只需直接在脚本中编写代码即可。毕竟,您希望 shell 解释脚本来计算echo "1" > ~/Desktop/in/foo
.甚至您不需要其他 shell 进程。这里不需要这里的文档。
我猜想另一个 shell 进程的预处理代码可能有意义(在某些情况下并且当你小心的时候),但是你应该使用 eg bash << EOF
,而不是read
.
另一件事:代码片段done < <(cat << EOF
可以简化为done << EOF
(请注意,此更改需要)
从代码末尾删除 )。