Bagaimana cara mencari file berdasarkan tipe file?

9

Saya tahu saya dapat menemukan file menggunakan find: find . -type f -name 'sunrise'. Contoh hasil:

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

Saya juga tahu bahwa saya dapat menentukan jenis file dari file: file sunrise. Contoh hasil:

sunrise: PEM RSA private key

Tetapi bagaimana saya bisa menemukan file berdasarkan tipe file?

Sebagai contoh, my-find . -type f -name 'sunrise' -filetype=bash-script:

./astronomy/sunrise
./schedule/sunrise
Aliran
sumber
1
Tidak ada --filetypeopsi untuk perintah find atau apa pun yang akan memberi tahu Anda jenis file. Satu-satunya hal yang dapat Anda lakukan adalah menggunakan --exec file {} \;dan kemudian memasukkannya ke dalam grep Bournejika Anda mencari skrip bash atau grep Perljika Anda mencari skrip Perl atau semacamnya.
Nasir Riley

Jawaban:

13

"Jenis file" pada sistem Unix adalah hal-hal seperti file biasa, direktori, pipa bernama, file karakter khusus, tautan simbolik dll. Ini adalah jenis file yang finddapat difilter dengan -typeopsi ini.

Itu find utilitas tidak dapat dengan sendirinya membedakan antara "script shell", "file gambar JPEG" atau lainnya jenis file biasa . Namun tipe data ini dapat dibedakan berdasarkan fileutilitas, yang melihat tanda tangan tertentu di dalam file itu sendiri untuk menentukan tipe mereka.

Cara umum untuk memberi label berbagai jenis file data adalah dengan jenis MIME mereka , dan filedapat menentukan jenis file MIME.


Menggunakan filedengan finduntuk mendeteksi jenis file MIME biasa, dan menggunakannya untuk hanya menemukan skrip shell:

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

atau, menggunakan bash,

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

Tambahkan -name sunrisesebelum -execjika Anda hanya ingin mendeteksi skrip dengan nama itu.

The findperintah di atas akan menemukan semua file reguler dalam atau di bawah direktori saat ini, dan untuk setiap panggilan file tersebut pendek in-line shell skrip. Script ini berjalan file -bipada file yang ditemukan dan keluar dengan status keluar nol jika output dari perintah itu berisi string /x-shellscript. Jika output tidak mengandung string itu, ia keluar dengan status keluar non-nol yang menyebabkanfind untuk segera melanjutkan dengan file berikutnya. Jika file tersebut ditemukan sebagai skrip shell, findperintah akan melanjutkan untuk menampilkan pathname file (yang -printpada akhirnya, yang juga bisa diganti dengan beberapa tindakan lain).

The file -biperintah akan menampilkan jenis MIME file. Untuk skrip shell di Linux (dan sebagian besar sistem lainnya), ini akan menjadi sesuatu seperti

text/x-shellscript; charset=us-ascii

sementara pada sistem dengan varian fileutilitas yang sedikit lebih tua , mungkin saja

application/x-shellscript

Bit yang umum adalah /x-shellscript substring.

Perhatikan bahwa pada macOS, Anda harus menggunakan file -bIbukan file -bikarena alasan ( -iopsi melakukan sesuatu yang sangat berbeda). Output pada macOS mirip dengan sistem Linux.


Apakah Anda ingin melakukan beberapa tindakan kustom pada setiap shell script yang berhasil ditemukan, Anda bisa melakukannya dengan yang lain -execdi tempat -printdi findperintah di atas, tetapi juga akan mungkin untuk melakukan

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 {} +

atau, dengan 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 {} +

Terkait:

Kusalananda
sumber
1

Anda dapat mengeksekusi findpada setiap file yang ditemukan dan kemudian menerima hasil yang Anda minati.

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

Saya menyarankan untuk membuat pola pencarian sedekat mungkin dengan harapan Anda agar jumlah kecocokan positif palsu tetap rendah.

Berhati-hatilah bahwa file dengan baris baru dalam nama file mereka dapat menyebabkan masalah dengan pendekatan ini.

Rolf
sumber
0

Menggunakan perl's File::LibMagicmodul:

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' -- .
Stéphane Chazelas
sumber