Sla*_*ast 35 shell bash quoting arguments
假设我想像这样通过 Bash 运行一个命令:
/bin/bash -c "ls -l"
Run Code Online (Sandbox Code Playgroud)
根据 Bash 手册页,我也可以这样运行它:
# don't process arguments after this one
# | pass all unprocessed arguments to command
# | |
# V V
/bin/bash -c ls -- -l
Run Code Online (Sandbox Code Playgroud)
除了它似乎不起作用(似乎被忽略了)。我做错了什么,还是我解释的手册页错误?
来自 man 的相关引用:
如果存在 -c 选项,则从字符串中读取命令。如果字符串后面有参数,则将它们分配给位置参数,从 $0 开始。
和
A -- 表示选项结束并禁用进一步的选项处理。-- 之后的任何参数都被视为文件名和参数。
god*_*eek 50
您正在错误地解释手册页。首先,关于--
发出选项结束信号的部分与您尝试做的事情无关。将-c
覆盖从该点的命令行的其余部分,使其不再打算通过在所有bash的选项处理,这意味着--
将通过该命令传递,而不是bash作为选项标记的最终处理。
第二个错误是将额外的参数作为位置参数分配给启动的 shell 进程,而不是作为参数传递给命令。所以,你想要做的可以作为以下之一来完成:
/bin/bash -c 'echo "$0" "$1"' foo bar
/bin/bash -c 'echo "$@"' bash foo bar
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,传递回显参数$0
和$1
显式,在第二种情况下,使用"$@"
扩展为“除 $0 之外的所有位置参数”。请注意,在这种情况下,我们还必须传递一些要使用的东西$0
;我选择了“bash”,因为这是$0
通常的情况,但其他任何东西都可以。
至于原因,它的完成这种方式,而不是刚好路过你直接给你列出命令的任何参数:请注意,文件说“命令小号,多是从字符串读”。换句话说,这个方案允许你做:
/bin/bash -c 'mkdir "$1"; cd "$1"; touch "$2"' bash dir file
Run Code Online (Sandbox Code Playgroud)
但是,请注意,实现原始目标的更好方法可能是使用env
而不是bash
:
/usr/bin/env -- "ls" "-l"
Run Code Online (Sandbox Code Playgroud)
如果您不需要 shell 提供的任何功能,则没有理由使用它 -env
在这种情况下使用它会更快、更简单并且输入更少。而且您不必费力去确保它可以安全地处理包含 shell 元字符或空格的文件名。
我不确定你的目标是什么,但如果你只是想建造一个鲁布戈德堡机器——“一种故意过度设计或过度设计的装置、发明、装置或装置,以在非常复杂的情况下执行非常简单的任务。复杂的时尚”——然后尝试
sh -c 'ls $0' -l
Run Code Online (Sandbox Code Playgroud)
或者
sh -c 'ls $1' supercalifragilisticexpialidocious -l
Run Code Online (Sandbox Code Playgroud)
甚至
sh -c 'ls -$0' l
Run Code Online (Sandbox Code Playgroud)
您应该能够从 Godlygeek 的回答中了解这些是如何工作的。
归档时间: |
|
查看次数: |
49573 次 |
最近记录: |