在bash中有条件(详细地)运行命令的最佳方法

时间:2020-09-21 16:54:22

标签: bash

我写了一个运行某些命令的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

尽管脚本现在正在运行,但我想知道是否有更好的方法来完成此任务。

1 个答案:

答案 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"
相关问题