Temukan jumlah file untuk setiap ekstensi dalam direktori

10

Saya ingin menghitung jumlah file untuk setiap ekstensi dalam direktori serta file tanpa ekstensi.

Saya telah mencoba beberapa opsi, tetapi saya belum menemukan solusi yang berfungsi:

  • find "$folder" -type f | sed 's/.*\.//' | sort | uniq -cadalah opsi tetapi tidak berfungsi jika tidak ada ekstensi file. Saya perlu tahu berapa banyak file yang tidak memiliki ekstensi.

  • Saya juga telah mencoba menemukan loop ke dalam array dan kemudian menjumlahkan hasilnya, tetapi saat ini kode itu melempar kesalahan variabel yang tidak dideklarasikan, tetapi hanya di luar loop:

    declare -a arr
    arr=()
    echo ${arr[@]}
    

    Ini melempar variabel yang tidak dideklarasikan, serta setelah loop pencarian selesai.

bocah traktor
sumber

Jawaban:

10
find "$path" -type f | sed -e '/.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/' -e 's/.*\.//' | LC_COLLATE=C sort | uniq -c

Penjelasan:

  • find "$path" -type f dapatkan daftar rekursif dari semua file di "$path"folder.
  • sed -e '/.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/' -e 's/.*\.//' ekspresi reguler:
    • /.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/ ganti semua file tanpa ekstensi dengan (tidak ada).
    • s/.*\.// dapatkan ekstensi dari file yang tersisa.
  • LC_COLLATE=C sort urutkan hasilnya, pertahankan simbol di atas.
  • uniq -c hitung jumlah entri berulang.
Helio
sumber
9

Menggunakan Python:

import os
from collections import Counter
from pprint import pprint

lst = []
for file in os.listdir('./'):
        name, ext = os.path.splitext(file)
        lst.append(ext)

pprint(Counter(lst))

Hasil:

Counter({'': 7,
         '.png': 4,
         '.mp3': 3,
         '.jpg': 3,
         '.mkv': 3,
         '.py': 1,
         '.swp': 1,
         '.sh': 1})
Ravexina
sumber
Anda mungkin bisa lolos dengan pemahaman daftar, seperti ext = [ f.split('.')[-1] for f in os.listdir('./') ] Thatll membuatnya lebih pendek beberapa baris dan mungkin lebih Pythonic
Sergiy Kolodyazhnyy
Terima kasih atas sarannya, saya hanya mencoba menuliskannya sejelas mungkin ...
Ravexina
1
Kejelasan adalah kebajikan :) Terutama dalam hal kode dan dokumentasi teknik.
Sergiy Kolodyazhnyy
6

Jika Anda memiliki GNU awk, Anda dapat melakukan sesuatu seperti

printf '%s\0' * | gawk 'BEGIN{RS="\0"; FS="."; OFS="\t"} 
  {a[(NF>1 ? $NF : "(none)")]++} 
  END{for(i in a) print a[i],i}
'

yaitu membangun / menambah array asosiatif yang dikunci pada .bidang yang dipisahkan terakhir , atau string tetap sewenang-wenang seperti (none)jika tidak ada ekstensi.

mawktampaknya tidak mengizinkan pemisah rekaman bita nol - Anda dapat menggunakan mawkpemisah baris baru default jika Anda yakin bahwa Anda tidak perlu berurusan dengan baris baru dalam nama file Anda:

printf '%s\n' * | mawk 'BEGIN{FS="."; OFS="\t"} {a[(NF>1 ? $NF : "(none)")]++} END{for(i in a) print a[i],i}'
Steeldriver
sumber
5

Dengan tugas dasar /bin/shatau bahkan bashbisa sedikit sulit, tetapi seperti yang Anda lihat di jawaban lain alat yang dapat bekerja pada data agregat dapat menangani tugas tersebut sangat mudah. Salah satu alat tersebut adalah sqlitedatabase.

Proses yang sangat sederhana untuk menggunakan sqlitedatabase adalah membuat .csvfile dengan dua bidang: nama file dan ekstensi. Nanti sqlitedapat menggunakan pernyataan agregat sederhana COUNT()dengan GROUP BY extuntuk melakukan penghitungan file berdasarkan bidang ekstensi

$ { printf "file,ext\n"; find -type f -exec sh -c 'f=${1##*/};printf "%s,%s\n" "${1}" "${1##*.}"' sh {} \; ; }  > files.csv
$ sqlite3 <<EOF
> .mode csv
> .import ./files.csv files_tb
> SELECT ext,COUNT(file) FROM files_tb GROUP BY ext;
> EOF
csv,1
mp3,6
txt,1
wav,27
Sergiy Kolodyazhnyy
sumber
files_tbtabel saya pikir sedang direferensikan tetapi kolom tabel tidak didefinisikan di mana pun saya bisa melihat?
WinEunuuchs2Unix
@ WinEunuuchs2Unix Mereka didefinisikan dalam file csv itu sendiri. Itulah yang pertama printfdilakukan. Dan SQLite akan secara default memperlakukan baris pertama file csv sebagai nama kolom.
Sergiy Kolodyazhnyy
1
Sangat mengesankan! +1
WinEunuuchs2Unix
5

Menggunakan PowerShell jika itu opsi:

Get-ChildItem -File | Group-Object Extension -NoElement

atau lebih pendek, menggunakan alias:

ls -file | group -n Extension
Joey
sumber
1
Wow! Jawaban pertama yang bagus! Saya bahkan tidak tahu PowerShell ada untuk Linux ... +1
Fabby
2
Terima kasih. Sudah ada cross-platform dan open-source untuk sementara waktu, tetapi ada pola pada SO dan SU di mana pertanyaan untuk skrip shell pada Windows sering dijawab dengan "Yah, instal cygwin dan gunakan bash, maka Anda dapat melakukan hal berikut ", jadi saya ragu untuk melakukan hal yang sama untuk situs Linux SE dengan alat yang berasal dari Windows. Tapi ini tugas yang bagus yang menunjukkan kekuatan PowerShell dengan cukup baik tanpa mengundang argumen lama tentang verbositas.
Joey