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

时间:2012-09-29 15:31:22

标签: bash file unix human-readable

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

  

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

上一个问题只询问了有多少常规文件,这很容易通过find . -type f | wc -l找出。

我只是在确定“人类可读内容”是什么时遇到了问题,因为我认为它除了二进制/汇编之外还有其他内容,但我认为这是-type f显示的内容。也许那就是教授所说的“技巧问题”?

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

2 个答案:

答案 0 :(得分: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

因此,第一部分要求您运行file命令并解析其输出。

  

我只是在确定“人类可读内容”是什么时遇到了问题,因为我认为它除了二进制/汇编之外还有其他任何内容,但我认为这就是-type f显示的内容。

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

  

也许这就是教授所说的“技巧问题”?

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


  

我认为教授希望我们能够对所有文件运行文件命令,并计算其中包含“text”的文件数。

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

  1. 如果您已经了解了这一点,可以使用xargsxargs运行另一个命令,使用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
    
  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
    
  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
    

    要理解这一点,-exec会反复调用file,将{}替换为找到的每个文件名。分号\;标记file命令的结尾。

答案 1 :(得分:0)

有一种简单明了的方法可以确定文件是否是人类可读的文本文件,只需使用file --mime-type <filename>并查找'text/plain'即可。无论文件是否具有结尾或者具有与.txt不同的结尾

,它都将起作用

所以你会这样做:

FILES=`find $YOUR_DIR -type f`

for file in $FILES ;
do

mime=`/usr/bin/file --mime-type $YOUR_DIR/$file | /bin/sed 's/^.* //'`

if [ $mime = "text/plain" ];  then      
    fileTotal=$(( fileTotal + 1 ))
    echo "$fileTotal - $file"
fi

done

echo "$fileTotal human readable files found!"

输出就像:

1 - /sampledir/samplefile
2 - /sampledir/anothersamplefile
....
23 human readable files found!

如果您想进一步了解更多人类可读的mime类型(例如,HTML和/或XML计数?),请查看http://www.feedforall.com/mime-types.htm