Bir dizindeki her uzantı için dosya sayısını bulma


10

Bir dizindeki her uzantı için dosya sayısını ve uzantısız dosyaları saymak istiyorum.

Birkaç seçeneği denedim, ancak henüz çalışan bir çözüm bulamadım:

  • find "$folder" -type f | sed 's/.*\.//' | sort | uniq -cbir seçenektir ancak dosya uzantısı yoksa çalışmaz. Kaç dosyanın bir uzantısı olmadığını bilmem gerekiyor.

  • Ayrıca bir dizi içine bir find döngü denedim ve sonra sonuçları toplamak, ancak şu anda bu kod bildirilmemiş bir değişken hata, ancak döngü dışında atar:

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

    Bu, buluntu döngüsü tamamlandıktan sonra bildirilmemiş bir değişken atar.

Yanıtlar:


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

Açıklama:

  • find "$path" -type f "$path"klasördeki tüm dosyaların özyinelemeli bir listesini alın .
  • sed -e '/.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/' -e 's/.*\.//' düzenli ifadeler:
    • /.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/ uzantı olmadan tüm dosyaları (none) ile değiştir.
    • s/.*\.// kalan dosyaların uzantısını alın.
  • LC_COLLATE=C sort sembolleri üstte tutarak sonucu sıralayın.
  • uniq -c tekrarlanan giriş sayısını sayın.

9

Python kullanma:

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))

Çıktı:

Counter({'': 7,
         '.png': 4,
         '.mp3': 3,
         '.jpg': 3,
         '.mkv': 3,
         '.py': 1,
         '.swp': 1,
         '.sh': 1})

Gibi Muhtemelen liste anlama kurtulabiliriz ext = [ f.split('.')[-1] for f in os.listdir('./') ] thatll o çift çizgiler daha kısa ve belki de daha Pythonic yapmak
Sergiy Kolodyazhnyy

Öneri için teşekkürler, ben sadece olabildiğince açık yazmaya çalışıyordum ...
Ravexina

1
Netlik erdemdir :) Özellikle kod ve mühendislik belgeleri söz konusu olduğunda.
Sergiy Kolodyazhnyy

6

GNU awk'iniz varsa, böyle bir şey yapabilirsiniz

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

yani, son .ayrılan alana anahtarlanmış ilişkilendirilebilir bir dizi veya bir (none)uzantı yoksa, isteğe bağlı olarak sabit bir dize oluşturmak / artırmak .

mawkboş bayt kayıt ayırıcısına izin vermiyor gibi görünüyor - mawkdosya adlarınızdaki yeni satırlarla uğraşmanıza gerek olmadığından eminseniz varsayılan satırsonu ayırıcısı ile kullanabilirsiniz :

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

5

Temel /bin/shveya hatta bashgörev biraz zor olabilir, ancak diğer cevaplarda da görebileceğiniz gibi, toplu veriler üzerinde çalışabilen araçlar bu görevle özellikle kolay başa çıkabilir. Böyle bir araç sqliteveritabanı olacaktır .

sqliteVeritabanını kullanmak için çok basit bir işlem .csviki alanlı bir dosya oluşturmak olacaktır : dosya adı ve uzantısı. Daha sonra sqlitebasit agrega deyimi kullanabilirsiniz COUNT()ile GROUP BY extuzatma alana bağlı dosyaların sayımını gerçekleştirmek için

$ { 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

files_tbbence tablo referans ediliyor ama tablo sütunları görebildiğim her yerde tanımlı değil mi?
WinEunuuchs2Unix

@ WinEunuuchs2Unix Bunlar csv dosyasının kendisinde tanımlanır. İlki printfbunu yapar. Ve SQLite varsayılan olarak csv dosyasının ilk satırını sütun adları olarak ele alır.
Sergiy Kolodyazhnyy

1
Çok etkileyici! +1
WinEunuuchs2Unix

5

Bu bir seçenekse PowerShell kullanma :

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

veya daha kısa, takma adlar kullanarak:

ls -file | group -n Extension

1
Vaov! Harika ilk cevap! Linux için PowerShell'in var olduğunu bile bilmiyordum ... +1
Fabby

2
Teşekkürler. Bir süredir çapraz platform ve açık kaynak var, ancak SO ve SU'da, Windows'ta kabuk komut dosyası oluşturma ile ilgili soruların genellikle "Eh, cygwin'i yükleyin ve bash kullanın" şeklinde yanıtlandığı bir desen vardı, o zaman aşağıdakileri yapabilirsiniz ", bu yüzden Windows kaynaklı araçlarla Linux SE siteleri için aynı şeyi yapmakta tereddüt ettim. Ancak bu, ayrıntılarla ilgili eski argümanı davet etmeden PowerShell'in güçlü yönlerini oldukça iyi gösteren güzel bir görevdi.
Joey
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.