在'bash -c'中添加参数


22

假设我想像这样通过Bash运行命令:

/bin/bash -c "ls -l"

根据Bash的手册页,我也可以这样运行它:

#               don't process arguments after this one
#               |   pass all unprocessed arguments to command
#               |   |
#               V   V
/bin/bash -c ls -- -l

除非它似乎不起作用(它似乎被忽略了)。我是在做错什么,还是我在解释手册页时出错?

男人的相关语录:

如果存在-c选项,则从字符串读取命令。如果字符串后面有参数,则将它们分配给位置参数,从$ 0开始。

A-表示选项结束,并禁用进一步的选项处理。-后面的任何参数均被视为文件名和参数。

Answers:


33

您将手册页解释为错误。首先,有关--发出信号结束选项的部分与您要执行的操作无关。-c从那时起,重写将覆盖命令行的其余部分,因此不再完全通过bash的选项处理,这意味着--该命令将传递给命令,而不是由bash作为选项结束标记处理。

第二个错误是额外的参数作为位置参数分配给启动的Shell进程,而不作为参数传递给命令。因此,您可以尝试执行以下操作之一:

/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar

在第一种情况下,传递呼应参数$0$1明确,而在第二种情况下,使用"$@"为正常扩展为“除$ 0的所有位置参数”。注意,在这种情况下,我们还必须传递一些要使用的东西$0。我选择了“ bash”,因为$0通常可以这样,但是其他任何方法都可以。

至于原因,它的完成这种方式,而不是刚好路过你直接给你列出命令的任何参数:请注意,文件说“命令小号,多是从字符串读”。换句话说,此方案允许您执行以下操作:

/bin/bash -c 'mkdir "$1"; cd "$1"; touch "$2"' bash dir file

但是,请注意,达到原始目标的更好方法可能是使用env而不是bash

/usr/bin/env -- "ls" "-l"

如果您不需要外壳程序提供的任何功能,则没有理由使用它- env在这种情况下使用将更快,更简单并且键入更少。而且,您不必费劲地确保它可以安全地处理包含shell元字符或空格的文件名。


3

我不确定您的目标是什么,但是如果您只是尝试构建Rube Goldberg机器 -“一种经过精心设计或过份设计的设备,发明,设备或设备,却无法在非常短的时间内完成非常简单的任务复杂的时尚” –然后尝试

sh -c 'ls $0' -l

要么

sh -c 'ls $1' supercalifragilisticexpialidocious -l

甚至

sh -c 'ls -$0' l

您应该能够从Godlygeek的答案中了解这些工作原理。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.