我对自动化日常任务感兴趣。直到最近,我的一个脚本的每个部分都运行得很顺利。但是现在我试图实现zenity,一切都崩溃了。现在我希望你能看看我做错了什么。
Soo,提到一点:我有一个残酷的bash脚本,看起来像这样:
#!/bin/bash
dosomething () {
# code
echo $1 >> ~/test.txt # For debugging
$1 & # ← Important line
# more code
}
main () {
# other code
dosomething "/usr/bin/rsync $rsync_options" # ← Call it "do_1"
dosomething "/usr/bin/find $findme_path -iname \"*.gpx\" -print0 | xargs -0 $other_command" # ← Call it "do_2"
# another code
}
( main | (zenity --progress $zenity_options || $still_another_command ) &
应该发生什么:main的输出通过管道传输到zenity(进度条)。 main并不真正执行任何命令,而是使用参数调用dosomething,该参数包含要执行的命令。 dosomething执行命令。
真正发生的事情:dosomething的“echo”部分与预期的一样。脚本执行后,do_1和do_2中的命令正确显示在〜/ test.txt中。 (如果我在终端中复制并粘贴〜/ test.txt的内容,则每个命令都会以预期结果执行。)
“do_1”的“重要行”将以预期结果执行。但“do_2”的“重要路线”似乎没有效果。至少,我在执行脚本后看不到$ other_command的影响。
我希望你至少能理解我的意思。如果你在这里给我一个提示出错的提示,那将是非常友好的。
答案 0 :(得分:1)
简短回答:见BashFAQ #50。
答案很长:当bash解析一行时,它会在进行变量替换之前解析引号和命令分隔符(|
等);结果,它在函数中运行$1 &
,$ 1的值中的引号和管道永远不会被解析,它们只是被传递给命令(在这种情况下为usr / bin / find)as争论的一部分。最终结果:它实际上运行的是/usr/bin/find $findme_path -iname '"*.gpx"' -print0 '|' xargs -0 $other_command"
。
通常,在这种情况下,我建议将命令作为一系列单词传递(即让函数运行"$@" &
,并将其称为dosomething /usr/bin/find $findme_path -iname "*.gpx" -print0
,但即使这样也无法处理命令中的管道 - 它仍将被视为另一个参数。
一种可能性是使用eval
。如果可能的话,应该避免这种情况,因为eval
是创建脚本错误的好方法 - 大量错误,微妙的错误,难以理解的错误,安全漏洞......它为增加了一层解析命令行中的所有,这意味着,例如,如果您尝试对名为Fred's file.txt
的文件进行操作,则会将该撇号作为引号并变得非常混乱。对碰巧包含反引号的文件进行操作太难以想象了。基本上,这是个坏消息。
在快速查看实际脚本之后,我推荐的是各种策略:尽可能多地隐藏shell函数中的命令复杂性,这样你就不会尝试传递管道并重定向到{ {1}}函数,然后使用我前面提到的单词系列方法。对于问题中的脚本,我会这样做:
dosomething
这意味着您的日志文件不会包含正在执行的管道的详细信息,只有#!/bin/bash
dosomething () {
# code
printf "%q " "$@" >> ~/test.txt # this gives a much better idea what's being done than echo $1 would
"$@" &
# more code
}
# hide the pipeline in a shell function
find_and_do_something () {
/usr/bin/find "$1" -iname "*.gpx" -print0 | xargs -0 $other_command
}
main () {
# other code
dosomething /usr/bin/rsync $rsync_options
dosomething find_and_do_something "$findme_path"
# another code
}
( main | (zenity --progress $zenity_options || $still_another_command ) &
,但至少它会起作用。
答案 1 :(得分:0)
您在哪里定义$other_command
?另请注意,您在末尾错过了一个结束括号(main
打开一个未关闭的括号。)