2012-09-29 54 views
5

我正在一個介紹課程UNIX,並且具有如下一門功課的問題:如何計算Bash中所有人類可讀的文件?

多少個文件在以前的問題是文本文件?文本文件是包含人可讀內容的任何文件。 (TRICK QUESTION)在一個文件上運行file命令來查看該文件是文本文件還是二進制數據文件!如果僅僅計算擴展名爲.txt的文件數,那麼這個問題就不會得到任何回答。)

上一個問題簡單地問了那裏有多少個常規文件,這很容易通過做find . -type f | wc -l弄清楚。

我只是無法確定「人類可讀內容」是什麼,因爲我假設它意味着除二進制/程序集之外的任何東西,但我認爲這就是-type f顯示的內容。也許這就是教授所說的「詭計問題」?

此問題稍後有一個後續問題,同時詢問「什麼文本文件包含大小寫混合的字符串」csc「?」。顯然「文本」指的不僅僅是.txt文件,但我需要弄清楚第一個問題來確定它!

+1

不,'find -type f'不包括目錄,設備節點等(「規範ial files「),即純文件以外的文件系統對象。它根本不檢查文件的內容,只檢查目錄條目(inode)中的類型信息。 Unix在「二進制」和「文本」文件之間沒有任何區別(並且對這個Unix的頭文件來說,任何試圖定義這種區別的嘗試都會變得很滑)。 – tripleee

回答

6

行情增加了淨度:

運行在一個文件中的「文件」命令來查看該文件是否爲文本文件或二進制數據文件!

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中的含義。很多文件甚至沒有文件擴展名!


我想教授希望我們能夠在所有文件上運行文件命令和計數的人,在這「文」的數量。

多部分答案如何?我將在#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 
    
  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命令的結束。

+0

當然,「人可讀」是人類的功能,而不是文件的功能。例如,我一直有一種強烈的印象,即大多數名爲README的文件事實上並不是大多數人可讀的。 – rici

+0

感謝您們的幫助,我知道該文件可以確定文件是否是'文本'文件,但我忘記提及有關查找常規文件的第一個問題的最終結果導致了153個文件(其目錄充滿了我們正在使用的子目錄),所以我認爲教授希望我們能夠在所有文件上運行文件命令並計算其中包含「文本」的文件命令的數量。假如可能的話,我會怎麼做呢? – Rekson

+0

@ user1687406更新了我的答案,將(find)和'file'結合起來的(overly)詳細解釋。我沒有進入如何「輸出」輸出。讓我知道你是否願意幫忙。 –

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