2012-09-29 30 views
5

Tôi đang tham gia một khóa học giới thiệu cho UNIX và có một câu hỏi bài tập về nhà mà sau:Làm cách nào để đếm tất cả các tệp có thể đọc được của con người trong Bash?

Có bao nhiêu tập tin trong câu hỏi trước là các tập tin văn bản? Tệp văn bản là bất kỳ tệp nào chứa nội dung có thể đọc được. (TRICK CÂU HỎI. Chạy lệnh tệp trên tệp để xem tệp đó là tệp văn bản hay tệp dữ liệu nhị phân! Nếu bạn chỉ cần đếm số lượng tệp có đuôi là .txt, bạn sẽ không nhận được điểm cho câu hỏi này.)

Câu hỏi trước chỉ đơn giản là hỏi có bao nhiêu tệp thông thường, có thể dễ dàng tìm ra bằng cách thực hiện find . -type f | wc -l.

Tôi chỉ gặp khó khăn trong việc xác định nội dung "nội dung có thể đọc được của con người", vì tôi giả sử nó có nghĩa là bất kỳ thứ gì ngoài nhị phân/lắp ráp, nhưng tôi nghĩ đó là màn hình -type f. Có lẽ đó là những gì giáo sư có nghĩa là bằng cách nói "câu hỏi lừa"?

Câu hỏi này có theo dõi sau đó cũng hỏi "Tệp văn bản nào chứa chuỗi" csc "trong bất kỳ kết hợp chữ hoa và chữ thường nào?". Rõ ràng "văn bản" đề cập đến nhiều hơn chỉ là các tệp .txt, nhưng tôi cần tìm ra câu hỏi đầu tiên để xác định điều này!

+1

Không, 'find-type f' loại trừ thư mục, nút thiết bị, v.v. ("spec tệp ial ") tức là đối tượng hệ thống tệp khác với tệp thuần túy. Nó không kiểm tra nội dung của các tập tin nào cả, chỉ là thông tin kiểu trong mục nhập thư mục (inode). Unix không tạo ra bất kỳ sự phân biệt nào giữa các tệp "nhị phân" và "văn bản" (và với đầu Unix này, bất kỳ nỗ lực nào để xác định sự phân biệt này đều đi vào một độ dốc trơn). – tripleee

Trả lời

6

Quotes thêm cho rõ ràng:

Chạy "tập tin" lệnh trên một tập tin để xem tập tin là một tập tin văn bản hoặc một tệp dữ liệu nhị phân!

Lệnh file sẽ kiểm tra tệp và cho bạn biết loại tệp nào của chúng. Từ "văn bản" sẽ (hầu như) luôn nằm trong phần mô tả cho các tệp văn bản.

Ví dụ:

desktop.ini: Little-endian UTF-16 Unicode text, with CRLF, CR line terminators 
tw2-wasteland.jpg: JPEG image data, JFIF standard 1.02 

Vì vậy, phần đầu tiên là yêu cầu bạn chạy lệnh file và phân tích sản lượng của nó.

Tôi chỉ gặp khó khăn khi xác định nội dung "có thể đọc được con người", vì tôi giả sử nó có nghĩa là bất kỳ thứ gì ngoài nhị phân/lắp ráp, nhưng tôi nghĩ đó là màn hình f.

find -type f tìm tệp. Nó lọc ra các đối tượng hệ thống tập tin khác như thư mục, liên kết tượng trưng và ổ cắm. Nó sẽ phù hợp với bất kỳ loại tập tin, mặc dù: tập tin nhị phân, tập tin văn bản, bất cứ điều gì.

Có thể đó là những gì giáo sư có nghĩa là bằng cách nói "câu hỏi lừa"?

Có vẻ như anh ấy chỉ nói không làm find -name '*.txt' hoặc một số lệnh như vậy để tìm tệp văn bản. Đừng giả sử một phần mở rộng tập tin cụ thể. Phần mở rộng tập tin có ý nghĩa ít hơn nhiều trong UNIX hơn là trong Windows. Rất nhiều tệp thậm chí không có phần mở rộng tệp!


Tôi đang nghĩ đến vị giáo sư muốn chúng ta có thể chạy lệnh tập tin trên tất cả các file và đếm số lượng của những người thân với 'text' trong đó.

Câu trả lời nhiều phần như thế nào? Tôi sẽ cung cấp cho các giải pháp đơn giản trong # 1, đó có lẽ là những gì giáo sư của bạn đang tìm kiếm. Và nếu bạn quan tâm, tôi sẽ giải thích những thiếu sót của nó và cách bạn có thể cải thiện nó.

  1. Một cách là sử dụng xargs, nếu bạn đã biết về điều đó. xargs chạy một lệnh khác, sử dụng dữ liệu từ stdin làm đối số của lệnh đó.

    $ 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. Điều đó có hiệu quả. Sắp xếp. Nó sẽ là đủ tốt cho một bài tập về nhà. Nhưng không đủ tốt cho một kịch bản thế giới thực.

    Hãy lưu ý cách nó bị hỏng trên tệp VMWare (copy).desktop vì nó có một khoảng trống trong đó. Điều này là do hành vi mặc định của xargs là tách các đối số trên khoảng trắng. Chúng tôi có thể khắc phục điều đó bằng cách sử dụng xargs -0 để phân tách đối số lệnh trên các ký tự NUL thay vì khoảng trắng. Tên tệp không thể chứa các ký tự NUL, vì vậy, tên này sẽ có thể xử lý mọi thứ.

    $ 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. Điều này đủ tốt cho kịch bản sản xuất và là thứ bạn sẽ gặp phải rất nhiều. Nhưng cá nhân tôi thích một cú pháp thay thế mà không yêu cầu một đường ống, và do đó là hơi hiệu quả hơn.

    $ 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 
    

    Để hiểu rằng, -exec gọi file lặp đi lặp lại, thay thế {} với mỗi tên tập tin mà nó tìm thấy. Dấu chấm phẩy \; đánh dấu sự kết thúc của lệnh file.

+0

Chắc chắn "con người có thể đọc được" là một chức năng của con người chứ không phải của tập tin. Tôi đã luôn luôn có ấn tượng mạnh mẽ rằng hầu hết các tập tin có tên README không phải là trong thực tế có thể đọc được bởi hầu hết mọi người, ví dụ. – rici

+0

Cảm ơn những người giúp đỡ, tôi biết rằng tệp có thể xác định tệp có phải là tệp 'văn bản' hay không, nhưng tôi quên đề cập đến kết quả cuối cùng của câu hỏi đầu tiên liên quan đến việc tìm kiếm các tệp thông thường dẫn đến 153 tệp (thư mục của nó) chứa đầy các thư mục con mà chúng tôi đang làm việc với), vì vậy tôi nghĩ giáo sư muốn chúng tôi có thể chạy lệnh tệp trên tất cả các tệp và đếm số lượng các thư mục có 'văn bản' trong đó.Làm thế nào tôi sẽ đi về làm điều đó, giả sử nó có thể? – Rekson

+0

@ user1687406 Cập nhật câu trả lời của tôi với một lời giải thích chi tiết (quá chi tiết) về việc kết hợp 'find' và' file'. Tôi đã không đi vào làm thế nào để 'grep' đầu ra. Hãy cho tôi biết nếu bạn muốn giúp đỡ với điều đó. –

0

có một cách thoải mái và dễ dàng để xác định xem một file là một file văn bản có thể đọc được con người, chỉ cần sử dụng file --mime-type <filename> và tìm kiếm 'text/plain'. Nó sẽ làm việc không có vấn đề nếu các tập tin có một kết thúc có hậu hay có một kết thúc khác nhau để .txt

Vì vậy, bạn sẽ làm gì sth như:

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!" 

và đầu ra sẽ được sth thích:

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

Nếu bạn muốn tiếp tục sử dụng các loại mime khác có thể đọc được (ví dụ: HTML và/hoặc số XML?), Hãy xem http://www.feedforall.com/mime-types.htm

Các vấn đề liên quan