Hitung file dalam direktori dengan ekstensi

15

Untuk keperluan pengujian, saya ingin menghitung berapa banyak file gambar di dalam direktori, memisahkan setiap jenis file gambar dengan ekstensi file (jpg = "yes". Ini karena nantinya akan berguna untuk skrip lain yang akan menjalankan suatu tindakan pada setiap ekstensi file). Dapatkah saya menggunakan sesuatu seperti berikut ini untuk file JPEG saja?

jpg=""
count=`ls -1 *.jpg 2>/dev/null | wc -l`
if [ $count != 0 ]
then
echo jpg files found: $count ; jpg="yes"
fi

Mengingat ekstensi file jpg, png, bmp, raw, dan lainnya, haruskah saya menggunakan whilesiklus untuk melakukan ini?

penjaga pintu
sumber

Jawaban:

14

Saya akan menyarankan pendekatan yang berbeda, menghindari kemungkinan masalah pemisahan kata ls

#!/bin/bash

shopt -s nullglob

for ext in jpg png gif; do 
  files=( *."$ext" )
  printf 'number of %s files: %d\n' "$ext" "${#files[@]}"

  # now we can loop over all the files having the current extension
  for f in "${files[@]}"; do
    # anything else you like with these files
    :
  done 

done

Anda bisa mengulang filesarray dengan perintah lain yang ingin Anda lakukan pada file dari setiap ekstensi tertentu.


Lebih mudah dibawa - atau untuk shell yang tidak menyediakan array secara eksplisit - Anda dapat menggunakan kembali array parameter posisi shell yaitu

set -- *."$ext"

dan kemudian ganti ${#files[@]}dan ${files[@]}dengan $#dan"$@"

Steeldriver
sumber
23

Pendekatan saya adalah:

  1. Daftar semua file dalam direktori
  2. Ekstrak ekstensi mereka
  3. Sortir hasilnya
  4. Hitung kemunculan setiap ekstensi

Semacam ini ( awkpanggilan terakhir murni untuk pemformatan):

ls -q -U | awk -F . '{print $NF}' | sort | uniq -c | awk '{print $2,$1}'

(dengan asumsi GNU di lssini untuk -Uopsi untuk melewatkan penyortiran sebagai optimasi. Ini dapat dihapus dengan aman tanpa mempengaruhi fungsi jika tidak didukung).

groxxda
sumber
mhmh ... nanti saya harus menyaring setiap ekstensi yang ditemukan untuk melakukan tindakan untuk itu?
watchmansky
Itu tergantung pada apa yang ingin Anda lakukan pada akhirnya. Bisakah Anda memberi informasi lebih lanjut?
groxxda
Tujuan saya: skrip yang memproses setiap file ekstensi (hanya file gambar) yang mengubah ukuran dari input data pengguna. Jadi, saya mulai dari berapa banyak file jpg yang ada, png berikutnya, dll.
watchmansky
solusi steeldrivers mungkin lebih tepat.
groxxda
2
Saya memiliki keduanya JPGdan jpgfile, dan menginginkannya secara rekursif sehingga solusi saya adalah untuk menulisfind . -type f | awk -F . '{print tolower($NF)}' | sort | uniq -c | awk '{print $2,":",$1}'
Kristian
11

Ini secara berulang menelusuri file dan menghitung ekstensi yang cocok:

$ find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'
   6 tiff
   7 bmp
  26 jpeg
  38 gif
  51 jpg
  54 png
Kit
sumber
6
find -type f | sed -e 's/.*\.//' | sort | uniq -c
Neik
sumber
3
Jangan lupa direktori awal dengan find. Juga, ini dapat membantu pembaca masa depan dari jawaban ini jika Anda memberikan penjelasan singkat tentang solusi Anda (jika mereka ingin memodifikasinya untuk kasus yang sedikit berbeda).
Jeff Schaller
Seberapa baik solusi ini menangani nama path yang mengandung spasi? Baris baru?
Dhag
1
finddefault ke direktori saat ini, itulah cara saya menggunakan ini. Saya tidak berpikir Tuhan bermaksud nama file memiliki ruang di dalamnya, tetapi ini berfungsi dengan baik untuk kasus itu. Jika Anda memiliki baris baru, maka Anda layak mendapatkan semua yang Anda dapatkan. Saya memikirkan penjelasan tetapi memutuskan akan membuat jawaban terlalu lama, saya pikir kesederhanaan adalah yang terpenting. 99% dari kasus dalam 1% dari waktu. Ini mungkin kompatibel dengan Versi 7.
Neik
3

Mungkin itu bisa menjadi lebih pendek

exts=( *.jpg *.png *.gif ); printf "There are ${#exts[@]}" extensions;
Valentin Bajrami
sumber
3

Apa pun yang terlibat lskemungkinan akan menghasilkan hasil yang tidak terduga dengan karakter khusus (ruang dan simbol lainnya). Setiap bashism (seperti array) tidak portabel. Apa pun yang melibatkan while readbiasanya lambat.

Di sisi lain, findSANGAT fleksibel (banyak opsi untuk difilter), ia memiliki [setidaknya] dua sintaks yang gagal aman untuk karakter khusus ... dan berskala baik pada direktori besar.

Untuk contoh ini, saya telah digunakan -inameuntuk mencocokkan nama ekstensi huruf besar dan kecil. Saya juga membatasi -maxdepth 1untuk menghormati pertanyaan Anda "di direktori saat ini". Daripada menghitung jumlah baris, di mana nama file dapat menyertakan CR / LF, -print0akan mencetak byte NULL pada akhir setiap nama file ... jadi | tr -d -c "\000" | wc -lmenghitung file dengan akurat (NULL bytes!).

extensions="jpg png gif"
for ext in $extensions; do
  c=$(find . -maxdepth 1 -iname "*.$ext" -print0 | tr -d -c "\000" | wc -c)
  if [ $c -gt 0 ]; then
    echo "Found $c  *.$ext files"

    find . -maxdepth 1 -iname "*.$ext" -print0 | xargs -0 -r -n1 DOSOMETHINGHERE
    # or #  find . -maxdepth 1 -iname "*.$ext" -exec "ls" "-l" "{}" ";"
  fi
done

PS -print0 | tr -d -c "\000" | wc -cdapat diganti dengan -printf "\000" | wc -catau bahkan -printf '\n' | wc -l.

Franklin Piat
sumber
0

hanya dapat menggunakan ls untuk sesuatu IMO sederhana ini

ls -l /opt/ssl/certs/*.pem | wc -l

atau

count=$(ls -l /some/folder/*.jpg | wc -l)

atau

ls *.{mp3,exe,mp4} 2>/dev/null | wc -l
Mike Q
sumber
-2

Jika Anda yakin dengan ekstensi tersebut, Anda bisa menggunakan findlike

find *.jpeg | wc -l
Nithish JV
sumber
sampai seseorang membuat touch $'foo\nbar.jpegdan itu akan dihitung dua kali, bukan satu kali. Atau lebih buruk, seseorang melakukannyamkdir directory.jpeg; touch directory.jpeg/{1..100}.txt
Jeff Schaller