Làm thế nào để tìm tập tin theo loại tập tin?


9

Tôi biết tôi có thể tìm thấy các tập tin bằng cách sử dụng find: find . -type f -name 'sunrise'. Kết quả ví dụ:

./sunrise
./events/sunrise
./astronomy/sunrise
./schedule/sunrise

Tôi cũng biết rằng tôi có thể xác định loại tệp của tệp : file sunrise. Kết quả ví dụ:

sunrise: PEM RSA private key

Nhưng làm thế nào tôi có thể tìm thấy các tập tin theo loại tập tin?

Ví dụ my-find . -type f -name 'sunrise' -filetype=bash-script:

./astronomy/sunrise
./schedule/sunrise

1
Không có --filetypetùy chọn cho lệnh find hoặc bất cứ điều gì khác sẽ cho bạn biết loại tệp. Điều duy nhất bạn có thể làm là sử dụng --exec file {} \;và sau đó chuyển nó vào grep Bournenếu bạn đang tìm kiếm các tập lệnh bash hoặc grep Perlnếu bạn đang tìm kiếm các tập lệnh Perl hoặc một cái gì đó dọc theo các dòng đó.
Nasir Riley

Câu trả lời:


13

"Loại tệp" trên hệ thống Unix là những thứ như tệp thông thường, thư mục, đường ống có tên, tệp đặc biệt ký tự, liên kết tượng trưng, ​​v.v ... Đây là loại tệp findcó thể lọc với -typetùy chọn của nó .

Các findtiện ích có thể không phải do bản thân phân biệt giữa một "shell script", "JPEG tập tin hình ảnh" hoặc bất kỳ khác loại tập tin thường xuyên . Tuy nhiên, các loại dữ liệu này có thể được phân biệt bởi filetiện ích, xem xét các chữ ký cụ thể trong chính các tệp để xác định loại của chúng.

Một cách phổ biến để gắn nhãn các loại tệp dữ liệu khác nhau là theo loại MIME của chúng và filecó thể xác định loại MIME của tệp.


Sử dụng filevới findđể phát hiện các kiểu MIME của tập tin thông thường, và việc sử dụng đó để chỉ tìm thấy kịch bản shell:

find . -type f -exec sh -c '
    case $( file -bi "$1" ) in
        */x-shellscript*) exit 0
    esac
    exit 1' sh {} ';' -print

hoặc, sử dụng bash,

find . -type f \
    -exec bash -c '[[ "$( file -bi "$1" )" == */x-shellscript* ]]' bash {} ';' \
    -print

Thêm vào -name sunrisetrước -execnếu bạn muốn chỉ phát hiện các tập lệnh có tên đó.

Các findlệnh trên sẽ tìm thấy tất cả các file thường xuyên trong hoặc dưới thư mục hiện hành, và cho mỗi cuộc gọi tập tin như vậy một đoạn ngắn shell script in-line. Kịch bản lệnh này chạy file -bitrên tệp tìm thấy và thoát với trạng thái thoát bằng 0 nếu đầu ra của lệnh đó chứa chuỗi /x-shellscript. Nếu đầu ra không chứa chuỗi đó, nó sẽ thoát với trạng thái thoát khác không, điều này sẽ findtiếp tục ngay lập tức với tệp tiếp theo. Nếu tệp được tìm thấy là tập lệnh shell, findlệnh sẽ tiến hành xuất tên đường dẫn của tệp ( -printở cuối, cũng có thể được thay thế bằng một số hành động khác).

Các file -bilệnh sẽ ra kiểu MIME của tập tin. Đối với tập lệnh shell trên Linux (và hầu hết các hệ thống khác), đây sẽ là một cái gì đó như

text/x-shellscript; charset=us-ascii

trong khi trên các hệ thống có biến thể cũ hơn một chút của filetiện ích, nó có thể là

application/x-shellscript

Các bit phổ biến là /x-shellscriptchuỗi con.

Lưu ý rằng trên macOS, bạn sẽ phải sử dụng file -bIthay file -bilý do ( -itùy chọn thực hiện một số thứ khá khác nhau). Đầu ra trên macOS tương tự như hệ thống Linux.


Bạn có muốn thực hiện một số hành động tùy chỉnh trên mỗi tập lệnh shell được tìm thấy không, bạn có thể làm điều đó với một tập lệnh khác -execthay cho -printcác findlệnh ở trên, nhưng cũng có thể thực hiện được

find . -type f -exec sh -c '
    for pathname do
        case $( file -bi "$pathname" ) in
            */x-shellscript*) ;;
            *) continue
        esac

        # some code here that acts on "$pathname"

    done' sh {} +

hoặc, với bash,

find . -type f -exec bash -c '
    for pathname do
        [[ "$( file -bi "$pathname" )" != */x-shellscript* ]] && continue

        # some code here that acts on "$pathname"

    done' bash {} +

Liên quan:


1

Bạn có thể thực thi findtrên mọi tệp tìm thấy và sau đó grep cho kết quả mà bạn quan tâm.

# When looking for ASCII Text
find . -type -exec file {} \; | grep "ASCII"
# or for MS Word Documents
find . -type f -exec file {} \; | grep "Microsoft Word"

Tôi đề nghị làm cho mẫu tìm kiếm càng gần càng tốt với mong đợi của bạn để giữ cho số lượng kết quả dương tính giả thấp.

Coi chừng các tệp có dòng mới trong tên tệp của chúng có thể gây ra sự cố với phương pháp này.


0

Sử dụng perl's File::LibMagicmô-đun:

perl -MFile::LibMagic=:easy -MFile::Find -le '
  find sub {
    print $File::Find::name if
      $_ eq "sunrise" and
      -f and
      MagicFile$_ eq "PEM RSA private key"
  }, @ARGV' -- .
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.