我写了一个运行某些命令的shell脚本(bash)。它可以选择不运行命令,而是将它们回显到屏幕上。默认情况下,这些命令的输出重定向到/ dev / null,但是还有另一个选项可以在屏幕上显示输出。
我使用一个函数来检查这些变量的值并运行命令或模拟它们:
runmaybe() {
if [[ true = $dry_run ]]; then
echo "Simulating '$@'"
else
if [[ true = $verbose ]]; then
$@
else
$@ > /dev/null
fi
fi
}
该功能正常运行,但是我遇到了一些复杂命令的问题,例如:
runmaybe eval svn cp $url $root/tags/$ntag -m \"Tagging revision with $ntag\"
我必须添加eval来防止wordsplitting,以便svn为-m选项获得正确的值。
该脚本中还有其他一些复杂的命令,例如:
runmaybe vzctl exec 1 "( cd /var/wwww/vhosts/myhost ; php cron.php )"
runmaybe ssh -t user@$host "vzctl exec $vmid \"( /usr/local/bin/myscript )\"" 2>/dev/null
runmaybe rsync --delete --exclude=\"**/.svn/\" --exclude=\"**/.git/\" --include=*.exe --numeric-ids -a $vOpt -H $LOCAL_VM$dir $host:$REMOTE_VM$dir
尽管脚本现在正在运行,但我想知道是否有更好的方法来完成此任务。
答案 0 :(得分:3)
问题在于$@
的引号未扩展。根据经验,如果看到$
,则应将其放在"
内。未引用的扩展会进行单词拆分和文件名扩展-为防止出现这种情况,请引用扩展。
我必须添加评估
eval
是邪恶的。不要使用它。
runmaybe() {
if [[ true = $dry_run ]]; then
echo "Simulating '$*'"
# or better quote with printf in some corner cases
printf "Simulating:"
printf " %q" "$@"
printf "\n"
elif [[ true = $verbose ]]; then
"$@"
else
"$@" > /dev/null
fi
}
runmaybe svn cp "$url" "$root/tags/$ntag" -m "Tagging revision with $ntag"
runmaybe rsync --delete --exclude="**/.svn/" --exclude="**/.git/" --include="*.exe" --numeric-ids -a "$vOpt" -H "$LOCAL_VM$dir" "$host:$REMOTE_VM$dir"