如何计算Bash中所有人类可读的文件?

Rek*_*son 5 unix bash file human-readable

我正在参加UNIX的入门课程,并有一个以下的作业问题:

上一个问题中有多少个文件是文本文件?文本文件是包含人类可读内容的任何文件.(TRICK QUESTION.在文件上运行file命令,看看文件是文本文件还是二进制数据文件!如果你只计算带有.txt扩展名的文件数,你就不会得到这个问题的分数.)

上一个问题只是询问有多少常规文件,这很容易弄清楚find . -type f | wc -l.

我只是在确定什么是"人类可读内容"时遇到了麻烦,因为我认为它除了二进制/汇编之外还意味着什么,但我认为这就是-type f显示的东西.也许这就是教授所说的"技巧问题"的含义?

这个问题后来有一个跟进,也问"什么文本文件包含字符串"csc"在任何大小写的混合?".显然"文本"指的不仅仅是.txt文件,但我需要弄清楚第一个问题来确定这个!

Joh*_*ica 6

为清晰起见,添加了引号:

对文件运行"file"命令以查看该文件是文本文件还是二进制数据文件!

file命令将检查文件并告诉您它们看起来是什么类型的文件."文本"一词(几乎)总是在文本文件的描述中.

例如:

desktop.ini:   Little-endian UTF-16 Unicode text, with CRLF, CR line terminators
tw2-wasteland.jpg: JPEG image data, JFIF standard 1.02
Run Code Online (Sandbox Code Playgroud)

所以第一部分是要求你运行file命令并解析它的输出.

我只是在确定什么是"人类可读内容"时遇到了麻烦,因为我认为它除了二进制/汇编之外还意味着什么,但我认为这就是-type f显示的内容.

find -type f找到文件.它过滤掉其他文件系统对象,如目录,符号链接和套接字.它将匹配任何类型的文件,但:二进制文件,文本文件,任何东西.

也许这就是教授所说的"技巧问题"的含义?

这听起来像他只是说不做find -name '*.txt'或某些这样的命令来查找文本文件.不要假设特定的文件扩展名.文件扩展名在UNIX中的含义远远低于在Windows中的含义.很多文件甚至没有文件扩展名!


我想教授希望我们能够对所有文件运行文件命令,并计算其中包含"text"的文件数.

多部分答案怎么样?我将在#1中提供直截了当的解决方案,这可能是您的教授正在寻找的.如果您有兴趣,我会解释它的缺点以及如何改进它.

  1. 一种方法是使用xargs,如果你已经了解了这一点.xargs运行另一个命令,使用来自stdin的数据作为该命令的参数.

    $ find . -type f | xargs file
    ./netbeans-6.7.1.desktop: ASCII text
    ./VMWare.desktop:         a /usr/bin/env xdg-open script text executable
    ./VMWare:                 cannot open `./VMWare' (No such file or directory)
    (copy).desktop:           cannot open `(copy).desktop' (No such file or directory)
    ./Eclipse.desktop:        a /usr/bin/env xdg-open script text executable
    
    Run Code Online (Sandbox Code Playgroud)
  2. 这样可行.有点.这对家庭作业来说已经足够了.但对于现实世界的剧本来说还不够好.

    注意它是如何破坏文件的,VMWare (copy).desktop因为它有一个空格.这是由于xargs在空格上拆分参数的默认行为.我们可以通过xargs -0在NUL字符而不是空格上拆分命令参数来解决这个问题.文件名不能包含NUL字符,因此可以处理任何内容.

    $ find . -type f -print0 | xargs -0 file
    ./netbeans-6.7.1.desktop: ASCII text
    ./VMWare.desktop:         a /usr/bin/env xdg-open script text executable
    ./VMWare (copy).desktop:  a /usr/bin/env xdg-open script text executable
    ./Eclipse.desktop:        a /usr/bin/env xdg-open script text executable
    
    Run Code Online (Sandbox Code Playgroud)
  3. 这对于生产脚本来说已经足够了,而且你会遇到很多东西.但我个人更喜欢不需要管道的替代语法,因此效率稍高.

    $ find . -type f -exec file {} \;
    ./netbeans-6.7.1.desktop: ASCII text
    ./VMWare.desktop:         a /usr/bin/env xdg-open script text executable
    ./VMWare (copy).desktop:  a /usr/bin/env xdg-open script text executable
    ./Eclipse.desktop:        a /usr/bin/env xdg-open script text executable
    
    Run Code Online (Sandbox Code Playgroud)

    要理解这一点,-execfile重复调用,替换{}它找到的每个文件名.分号\;标志着file命令的结束.