命令参数的位置

Yve*_*ves 0 command-line command arguments

我认为任何命令的参数位置都是不固定的。

例如,cp -r ./abc ./def并且cp ./abc ./def -r是相同的,grep -rnH hello .并且grep hello . -rnH是相同的......

但是,今天我在使用的时候ldd,发现我错了。因为ldd -r x.soldd x.so -r不一样。第二个命令给了我一个错误:

ldd: ./-r: No such file or directory
Run Code Online (Sandbox Code Playgroud)

为什么我们不能改变参数的位置ldd

Kus*_*nda 6

一些 GNU 实用程序会默默地重新组织命令行参数,以便选项和选项参数位于操作数之前。这不是标准行为。

符合标准的实用程序期望选项和选项参数首先出现,并且当命令行解析器找到第一个非选项参数时,其余参数被视为操作数:

cp -i file1 file2
Run Code Online (Sandbox Code Playgroud)

在上面,第一个参数是一个选项,而最后两个参数是操作数。

cp file1 file2 -i
Run Code Online (Sandbox Code Playgroud)

上面有三个操作数,一个非 GNU 实现cp会复制file1file2进入被调用的目录-i(如果不存在这样的目录,则给出错误消息)。cp另一方面,GNU将其-i视为一个选项并询问我是否要覆盖file2该文件是否存在。

通过设置环境变量来纠正此行为POSIXLY_CORRECT

$ cp file1 file2 -i
cp: overwrite 'file2'? n

$ POSIXLY_CORRECT=1 cp file1 file2 -i
cp: target '-i' is not a directory
Run Code Online (Sandbox Code Playgroud)

或者你可以使用--明确地标记选项的结束(这会工作的命令是否解析其选项的GNU方式与否):

$ cp -- file1 file2 -i
cp: target '-i' is not a directory
Run Code Online (Sandbox Code Playgroud)

在以下方面需要牢记这一点:

grep 'PATTERN' *.txt
Run Code Online (Sandbox Code Playgroud)

使用 GNU,grep您需要编写:

grep -- 'PATTERN' *.txt
Run Code Online (Sandbox Code Playgroud)

或者

grep -e 'PATTERN' -- *.txt
Run Code Online (Sandbox Code Playgroud)

如果PATTERN某些.txt文件的或 名称以-.

您的ldd(在 GNU 系统上是一个bash手动解析选项的脚本,不使用 GNU getopt_long()API)没有以“GNU 方式”解析其命令行参数,这(恕我直言)它是正确的。


来自 GNU 文档getopt_long(3)

默认情况下,getopt()argv扫描时置换 的内容,以便最终所有非选项都在最后。[...] 如果optstringis的第一个字符+POSIXLY_CORRECT设置了环境变量,则一旦遇到非选项参数,选项处理就会停止。