如何向Bash函数传递含&&运算符的多条命令?
解决Bash函数支持传入
&&连接的多条命令问题 问题场景
我需要把用&&连接的多条命令传入单个Bash函数调用中,由于每条命令的参数数量不固定,原本用$@捕获所有参数,单条命令时函数运行正常:
function try_log () { $@ \ && echo "PASS!" || echo "FAIL!" } $ try_log touch foo bar PASS! $ try_log rm foo bar PASS! $ try_log rm foo bar rm: cannot remove 'foo': No such file or directory rm: cannot remove 'bar': No such file or directory FAIL!
但想要支持&&连接的命令串时,几次尝试都失败了:
try_log ls && ls # 第二条ls会在第一个命令完成后单独执行 foo bar PASS! foo bar try_log 'ls && ls' ls: cannot access '&&': No such file or directory ls: cannot access 'ls': No such file or directory FAIL! $ try_log `ls && ls` foo: command not found FAIL!
可行解决方案
方案1:用eval解析执行命令串
修改函数,通过eval识别&&这类shell语法,把传入的命令串当作shell代码执行:
function try_log () { eval "$@" && echo "PASS!" || echo "FAIL!" }
使用示例:
try_log 'ls && echo "执行完成"' # 先执行ls,成功后输出"执行完成",最后输出PASS!
注意:eval会直接执行传入的内容,要确保命令来源安全,避免恶意注入。
方案2:调用子shell执行命令
通过bash -c启动子shell,让子shell解析执行包含&&的命令串:
function try_log () { bash -c "$*" && echo "PASS!" || echo "FAIL!" }
使用示例:
try_log 'ls foo && rm foo' # 只有ls成功时才会执行rm,整个命令串成功后输出PASS!
这里用$*把所有参数拼接成单个字符串,传给子shell作为执行代码。
方案3:传递代码块(更安全)
直接把命令作为代码块传递给函数,避免字符串解析的问题:
function try_log () { "$@" && echo "PASS!" || echo "FAIL!" }
使用时用括号或大括号包裹命令:
# 用小括号(会在子shell执行) try_log ( ls && ls ) # 用大括号(当前shell执行,注意空格和分号) try_log { ls && ls; }
这种方式没有注入风险,语法也更直观。
失败原因说明
try_log ls && ls:shell会优先解析&&,把try_log ls和ls拆成两个独立命令执行,所以第二条ls会单独运行。try_log 'ls && ls':$@会把整个字符串当作ls命令的参数,即执行ls '&&' 'ls',ls会把&&和ls当成文件名,自然报错。try_logls && ls``:反引号会先执行ls && ls,把输出结果作为参数传给try_log,比如当前目录有foo文件,就会变成try_log foo,shell尝试执行foo命令,导致报错。
内容的提问来源于stack exchange,提问作者J'e
相关产品推荐
相关产品推荐

