我运行命令file -- *
并得到以下输出:
-file04: data
-file05: data
-file06: data
-file07: ASCII text
所以它基本上打印文件名和内容类型。但参数是什么意思呢?
答案1
file -- *
这里是 Unix shell 语言的代码。 Unix shell 语言,专门用于在新进程中查找和启动命令,向它们传递参数和环境变量,并检查它们的标准输入/输出/错误流。
该语言很初级,但有一些奇特的功能。
示例中的该行简单的命令在shell语言语法中。
空格用于分隔单词。这里file
,--
和*
。
这里的第一个单词file
被视为要运行的命令的名称。 shell 将使用特殊变量查找该命令的路径$PATH
。我可能是这样的/usr/bin/file
。
该*
单词包含 shell 通配符 (*
),因此它会触发 shell 的一个特殊功能,称为文件名生成或者通配(POSIX 称之为路径名扩展)。 shell 将替换*
为与该模式匹配的文件名列表。*
是匹配任意数量字符的模式。因此 shell 会将其扩展为当前目录中所有文件的名称(隐藏文件除外),按字母顺序排序。
然后 shell 将分叉一个子进程,并且在该子进程中将以/usr/bin/file
、file
和--
文件名列表(因此在您的情况下-file04
,-file05
...)作为参数执行。
该file
命令是一个独立于 的命令sh
。sh
的工作是解析命令行,而file
的工作是尝试识别文件内容的性质。
启动后,像大多数命令一样,file
将解析其参数。第一个file
,只是告诉它如何调用它,它应该如何像在错误消息中一样引用自身。接下来的参数告诉它要做什么。
与大多数命令一样,以 开头的参数-
被视为选项。这里,第一个参数是--
。从技术上讲,它不是一个选项,而是选项结束标记。它告诉file
它应该从现在开始停止处理选项,并且下一个参数不应被视为选项,即使它们以-
.
这是一件好事,因为下一个参数 ,-file01
实际上并不意味着被视为一个选项,而是一个用于file
告诉其内容性质的文件名。
当传递以(也可能是某些命令的问题)--
开头的非选项参数或可能以/开头的参数时,您需要这样做,当它们是某些扩展的结果时,例如使用, , , ...时-
+
-
+
cmd -- "$arg"
cmd -- *
cmd -- "${args[@]}"
cmd -- $(cmd2)
如果不这样做可能会导致错误和安全漏洞。
对于意味着文件路径的参数,另一种方法是为不以(/
开头的参数添加前缀,并且是同一文件的路径,但只有后者可以作为选项)。对于不支持作为选项结束标记的命令来说,使用该方法可能是必要的,并且还可以解决其他问题,例如单独被解释为意味着 stdin 而不是调用的文件,即使在, or的处理之后传递包含 的参数。./
./-foo/bar
-foo/bar
--
-
-
--
awk
=
答案2
大多数 GNU 控制台实用程序无法处理以破折号开头的文件,除非您传递--
给它们,例如
$ cat -file1
产生
cat: invalid option -- 'f'
Try 'cat --help' for more information.
这就是为什么在您的情况下--
是必需的,因为它指示file
实用程序停止处理选项并将其余参数视为文件。
我想知道是否可以以某种方式利用这种特性,因为它看起来确实是一个可行的选择。向某人发送一些文件(例如 tar 存档)并要求他们执行某些操作,例如command *
.以破折号开头的文件将被解释为选项,除非用户进行了尽职调查,而大多数人没有进行尽职调查。例如,我不记得上次使用是什么时候,--
因为我没有以破折号开头的单个文件。