file $(ls /usr/bin/* | grep zip) 命令给我错误。怎么了?

file $(ls /usr/bin/* | grep zip) 命令给我错误。怎么了?

我决定读一本关于 Linux/Unix 的书。我已经读到了一章,他们试图解释如何将命令的输出作为扩展传递到 shell。

以下命令

file $(ls /usr/bin/* | grep zip)

给我错误“无法打开“文件名(没有这样的文件或目录)”。相反,当我这样做时

file $(ls | grep zip)

无论文件夹如何,一切都会正常显示。为什么?这是某种论证限制吗?

如果我这样做

file $(ls Pictures/ | grep jpg)

我得到以下信息:

1234.jpg: ERROR: cannot open 1234.jpg (No such file or directory)

向右移动到我想要列出的目录时

nassosdim@ubuntu:~$ cd Pictures/

nassosdim@ubuntu:~/Pictures$ file $(ls | grep jpg)

打印出文件的结果

1234.jpg: JPEG image data, JFIF standard 1.01

有人可以向我解释一下发生了什么事吗? :(

答案1

出现错误是因为 bash 试图*使用 glob 模式匹配将参数中的 扩展为 ls 。当 glob 与模式不匹配时,它总是会出现这样的错误。 then作为真正的星号*传递ls,它也不匹配文件,因此ls会出错!

关于您正在做的事情,有几处是多余的。我知道您正在尝试学习一个结构,但让我们分解一下您刚刚完成的一些内容以及如何完成它。

  1. ls /usr/bin足以列出 bin 目录中的文件,您根本不需要星号。
  2. 你永远不应该解析输出ls无论如何,它是模棱两可的并且有潜在的危险。
  3. 您可以通过执行以下操作获得相同的效果,而无需 grep ls /usr/bin/*zip*,但这ls仍然是多余的,您可以将 glob 扩展传递给文件:file /usr/bin/*zip*

最后,find通常是查找文件的更好工具。你可以像这样做你想做的事:

$ find /usr/bin -iname '*zip*' -exec file {} +

答案2

shell 扩展*并将命令转换为file $(ls /usr/bin/a /usr/bin/b /usr/bin/whatever | grep zip).您不需要在 UNIX 中指定星号,除非您希望 shell 在将其传递到ls.

即你的 shell 将 * 替换为每个匹配的文件它运行命令,如果您习惯了的话,这不是它在 Windows 上的工作方式。

请阅读此处第 3.4.9 节

file $(ls /usr/bin/ | grep zip) 

是正确的方法(从某种意义上说,您不需要 *,但请参阅 Caleb 的答案以了解其他问题和选项)。但请注意,实际上运行的是,

file /usr/bin/a /usr/bin/b /usr/bin/whatever

不是

file /usr/bin/a
file /usr/bin/b
file /usr/bin/whatever

再次强调,它的做法与 Windows 不同。

答案3

请尝试ls /usr/bin/* | grep zip看看您正在提供哪些论据file。我对结果有点困惑。在我的Ubuntu系统上,结果是这样的:

/usr/bin/funzip
/usr/bin/gpg-zip
/usr/bin/mzip
/usr/bin/preunzip
/usr/bin/prezip
/usr/bin/prezip-bin
/usr/bin/unzip
/usr/bin/unzipsfx
/usr/bin/zip
/usr/bin/zipcloak
/usr/bin/zipgrep
/usr/bin/zipinfo
/usr/bin/zipnote
/usr/bin/zipsplit
funzip
gpg-zip
mzip
preunzip
prezip
prezip-bin
unzip
unzipsfx
zip
zipcloak
zipgrep
zipinfo
zipnote
zipsplit

使用ls /usr/bin/* | less我们可以看到为什么会得到这样的结果:在 /usr/bin 中的所有文件之后,ls还列出了 /usr/bin/X11 目录的内容,并且列出了它们,并且没有预先添加目录名称。

当您将这些没有目录名的文件名提供给 时filefile无法找到这些文件,并且您会收到“没有这样的文件或目录”错误消息(附注:如果您收到错误消息,请不要只说“我有错误”,但发布错误消息)。

就像 Caleb 已经发布的那样,只需使用file /usr/bin/*zip*.

答案4

ls由于输出格式各不相同,解析结果可能是一件有风险的事情。你最好做这样的事情:

file /path/to/*.zip

尝试使用更简单的命令来演示进程替换的工作原理:

ls $(echo /usr/bin) 

相关内容