AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 795599
Accepted
IanC
IanC
Asked: 2016-07-07 07:51:56 +0800 CST2016-07-07 07:51:56 +0800 CST 2016-07-07 07:51:56 +0800 CST

为什么命令“ls | file”不起作用?

  • 772

我一直在研究命令行并了解到|(管道)旨在将输出从命令重定向到另一个命令的输入。那么为什么命令ls | file不起作用呢?

file输入是多个文件名之一,例如file filename1 filename2

ls输出是文件夹上的目录和文件列表,所以我认为ls | file应该显示文件夹上每个文件的文件类型。

但是,当我使用它时,输出是:

    Usage: file [-bcEhikLlNnprsvz0] [--apple] [--mime-encoding] [--mime-type]
        [-e testname] [-F separator] [-f namefile] [-m magicfiles] file ...
    file -C [-m magicfiles]
    file [--help]

由于该file命令的使用存在一些错误

command-line
  • 8 8 个回答
  • 8786 Views

8 个回答

  • Voted
  1. Best Answer
    John Kugelman
    2016-07-07T09:15:57+08:002016-07-07T09:15:57+08:00

    根本问题是file期望文件名作为命令行参数,而不是标准输入。当您编写ls | file的输出ls作为输入传递给file. 不作为参数,作为输入。

    有什么不同?

    • 命令行参数是当您在命令后写入标志和文件名时,如cmd arg1 arg2 arg3. 在 shell 脚本中,这些参数可用作变量$1、$2、$3等。在 C 中,您可以通过char **argv和int argc参数访问它们main()。

    • 标准输入 stdin 是一个数据流。一些程序在没有任何命令行参数时喜欢cat或从标准输入读取。wc在 shell 脚本中,您可以使用它read来获取单行输入。在 C 中,您可以在各种选项中使用scanf()or 。getchar()

    file通常不从标准输入读取。它期望至少有一个文件名作为参数传递。这就是为什么它会在您编写时打印出用法ls | file,因为您没有传递参数。

    您可以使用xargs将标准输入转换为参数,如ls | xargs file. 尽管如此,正如terdon 提到的,解析ls是一个坏主意。最直接的方法就是:

    file *
    
    • 70
  2. terdon
    2016-07-07T08:47:50+08:002016-07-07T08:47:50+08:00

    因为,正如您所说,的输入file必须是filenames。ls然而,的输出只是文本。它恰好是文件名列表并没有改变它只是文本而不是硬盘驱动器上文件位置的事实。

    当您看到屏幕上打印的输出时,您看到的是文本。该文本是一首诗还是一个文件名列表对计算机没有影响。它只知道它是文本。这就是为什么您可以将 的输出传递ls给将文本作为输入的程序(尽管您真的,真的不应该):

    $ ls / | grep etc
    etc
    

    因此,要使用将文件名列为文本(例如ls或find)的命令的输出作为采用文件名的命令的输入,您需要使用一些技巧。典型的工具是xargs:

    $ ls
    file1 file2
    
    $ ls | xargs wc
     9  9 38 file1
     5  5 20 file2
    14 14 58 total
    

    不过,正如我之前所说,您真的不想解析ls. 类似的东西find更好(在每个文件名之后print0打印 a\0而不是 newilne ,而-0ofxargs让它处理这样的输入;这是使您的命令与包含换行符的文件名一起工作的技巧):

    $ find . -type f -print0 | xargs -0 wc
     9  9 38 ./file1
     5  5 20 ./file2
    14 14 58 total
    

    它也有自己的方法,xargs根本不需要:

    $ find . -type f -exec wc {} +
     9  9 38 ./file1
     5  5 20 ./file2
    14 14 58 total
    

    最后,您还可以使用 shell 循环。但是,请注意,在大多数情况下,xargs会更快、更有效率。例如:

    $ for file in *; do wc "$file"; done
     9  9 38 file1
     5  5 20 file2
    
    • 18
  3. Braiam
    2016-07-07T09:26:50+08:002016-07-07T09:26:50+08:00

    得知'|' (管道)旨在将输出从命令重定向到另一个命令的输入。

    它不会“重定向”输出,而是获取程序的输出并将其用作输入,而 file 不接受输入,而是将文件名作为参数,然后对其进行测试。重定向不会将这些文件名作为参数传递,管道也不会,您正在做的事情越晚。

    --files-from如果您有一个列出所有要测试的文件的文件,您可以做的是从文件中读取文件名,否则只需将文件的路径作为参数传递。

    • 6
  4. Schmuddi
    2016-07-07T15:17:29+08:002016-07-07T15:17:29+08:00

    接受的答案解释了为什么管道命令不能立即工作,并且使用该file *命令,它提供了一个简单、直接的解决方案。

    我想提出另一种可能在某个时候派上用场的替代方案。诀窍是使用反引号(`)字符。反引号在这里有非常详细的解释。简而言之,它获取包含在反引号中的命令的输出,并将其作为字符串替换为剩余的命令。

    因此,find `ls`将获取ls命令的输出,并将其替换为find命令的参数。这比公认的解决方案更长、更复杂,但它的变体在其他情况下可能会有所帮助。

    • 6
  5. Mark Williams
    2016-07-07T08:03:01+08:002016-07-07T08:03:01+08:00

    通过管道的输出ls是一个实心数据块,每行以 0x0a 分隔 - 即换行符 - 并将file其作为一个参数,它期望多个字符一次处理一个。

    作为一般规则,永远不要使用ls为其他命令生成数据源 - 有一天它会通过管道 .. 进入rm,然后你就有麻烦了!

    最好使用循环,例如for i in *; do file "$i" ; done可以预测地产生您想要的输出。如果文件名带有空格,则会出现引号。

    • 5
  6. deamentiaemundi
    2016-07-07T10:55:40+08:002016-07-07T10:55:40+08:00

    如果您想使用管道来馈送,请使用通常后跟文件名file的选项,但您也可以使用单个连字符从标准输入读取,所以-f-

    $ ls
    cow.pdf  some.txt
    $ ls | file -f -
    cow.pdf:       PDF document, version 1.4
    some.txt:        ASCII text
    

    连字符的技巧-适用于许多标准命令行实用程序(尽管--有时是这样),所以它总是值得一试。

    该工具xarg功能更强大,并且在大多数情况下仅在参数列表太长时才需要(有关详细信息,请参阅此帖子)。

    • 4
  7. SuperKrish
    2016-07-08T23:54:50+08:002016-07-08T23:54:50+08:00

    它可以使用如下命令

    ls | xargs file
    

    它对我来说会更好

    • 2
  8. matth
    2017-02-16T03:02:10+08:002017-02-16T03:02:10+08:00

    这也应该有效:

    file $(ls)
    

    在这里也讨论过:https ://unix.stackexchange.com/questions/5778/whats-the-difference-between-stuff-and-stuff

    • 1

相关问题

  • 如何从命令行仅安装安全更新?关于如何管理更新的一些提示

  • 如何从命令行刻录双层 dvd iso

  • 如何从命令行判断机器是否需要重新启动?

  • 文件权限如何工作?文件权限用户和组

  • 如何在 Vim 中启用全彩支持?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve