ค้นหาจำนวนไฟล์สำหรับแต่ละส่วนขยายในไดเรกทอรี


10

ฉันต้องการนับจำนวนไฟล์สำหรับแต่ละส่วนขยายในไดเรกทอรีรวมถึงไฟล์ที่ไม่มีนามสกุล

ฉันลองตัวเลือกสองสามตัวแล้วแต่ยังไม่พบวิธีแก้ปัญหาที่ใช้งานได้:

  • find "$folder" -type f | sed 's/.*\.//' | sort | uniq -cเป็นตัวเลือก แต่ใช้ไม่ได้หากไม่มีนามสกุลไฟล์ ฉันจำเป็นต้องรู้ว่ามีไฟล์กี่ไฟล์ที่ไม่มีนามสกุล

  • ฉันได้ลองค้นหาวนรอบในอาร์เรย์แล้วรวมผล แต่ในเวลานี้รหัสโยนข้อผิดพลาดตัวแปรไม่ได้ประกาศ แต่เฉพาะนอกวง:

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

    สิ่งนี้จะโยนตัวแปรที่ไม่ได้ประกาศเช่นเดียวกับเมื่อการค้นหาวนเสร็จสมบูรณ์

คำตอบ:


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

คำอธิบาย:

  • find "$path" -type f รับรายการซ้ำของไฟล์ทั้งหมดใน"$path"โฟลเดอร์
  • sed -e '/.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/' -e 's/.*\.//' นิพจน์ทั่วไป:
    • /.*\/[^\/]*\.[^\/]*$/!s/.*/(none)/ แทนที่ไฟล์ทั้งหมดโดยไม่มีนามสกุลด้วย (ไม่มี)
    • s/.*\.// รับนามสกุลของไฟล์ที่เหลือ
  • LC_COLLATE=C sort จัดเรียงผลการรักษาสัญลักษณ์ที่ด้านบน
  • uniq -c นับจำนวนรายการซ้ำ

9

ใช้ 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))

ผลลัพธ์:

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

คุณอาจหนีความเข้าใจในรายการไปได้เช่น ext = [ f.split('.')[-1] for f in os.listdir('./') ] Thatll ทำให้คู่สั้นลงและอาจเป็น Pythonic มากกว่าเดิม
Sergiy Kolodyazhnyy

ขอบคุณสำหรับคำแนะนำผมก็แค่พยายามที่จะเขียนมันเป็นที่ชัดเจนเท่าที่จะทำได้ ...
Ravexina

1
ความชัดเจนเป็นคุณธรรม :) โดยเฉพาะอย่างยิ่งเมื่อมันมาถึงรหัสและเอกสารทางวิศวกรรม
Sergiy Kolodyazhnyy

6

หากคุณมี GNU awk คุณสามารถทำอะไรได้บ้าง

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

เช่นสร้าง / เพิ่มอาร์เรย์เชื่อมโยงคีย์บน.เขตข้อมูลที่แยกล่าสุดหรือบางสตริงคงที่โดยพลการเช่น(none)ถ้าไม่มีส่วนขยาย

mawkดูเหมือนจะไม่อนุญาตให้ใช้ตัวคั่นเร็กคอร์ด null-byte - คุณสามารถใช้mawkกับตัวคั่นบรรทัดใหม่ที่เป็นค่าเริ่มต้นหากคุณมั่นใจว่าคุณไม่จำเป็นต้องจัดการกับบรรทัดใหม่ในชื่อไฟล์ของคุณ:

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

5

ด้วยพื้นฐาน/bin/shหรือแม้แต่bashงานอาจเป็นเรื่องยากเล็กน้อย แต่อย่างที่คุณเห็นในคำตอบอื่น ๆ เครื่องมือที่สามารถทำงานกับข้อมูลรวมสามารถจัดการกับงานดังกล่าวได้ง่ายเป็นพิเศษ เครื่องมือหนึ่งดังกล่าวจะเป็นsqliteฐานข้อมูล

กระบวนการง่ายๆในการใช้sqliteฐานข้อมูลคือการสร้าง.csvไฟล์ที่มีสองฟิลด์: ชื่อไฟล์และนามสกุล ในภายหลังsqliteสามารถใช้คำสั่งรวมอย่างง่ายCOUNT()ด้วยGROUP BY extเพื่อดำเนินการนับไฟล์ตามฟิลด์ส่วนขยาย

$ { 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_tbตารางที่ฉันคิดว่าถูกอ้างอิง แต่คอลัมน์ตารางไม่ได้ถูกกำหนดไว้ทุกที่ที่ฉันเห็น
WinEunuuchs2Unix

@ WinEunuuchs2Unix พวกเขากำลังกำหนดไว้ในไฟล์ csv เอง นั่นคือสิ่งแรกที่printfทำ และ SQLite จะใช้ค่าเริ่มต้นในการรักษาบรรทัดแรกของไฟล์ csv เป็นชื่อคอลัมน์
Sergiy Kolodyazhnyy

1
ที่น่าประทับใจมาก! +1
WinEunuuchs2Unix

5

ใช้PowerShellหากเป็นตัวเลือก:

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

หรือสั้นกว่าโดยใช้นามแฝง:

ls -file | group -n Extension

1
ว้าว! คำตอบแรกที่ดี! ฉันไม่รู้ด้วยซ้ำว่ามี PowerShell สำหรับ Linux ... +1
Fabby

2
ขอบคุณ มันมีอยู่ข้ามแพลตฟอร์มและโอเพ่นซอร์สมาระยะหนึ่งแล้ว แต่มีรูปแบบเกี่ยวกับ SO และ SU ที่คำถามสำหรับการเชลล์สคริปต์บน Windows ได้รับการตอบด้วย "ดีติดตั้ง cygwin และใช้ bash จากนั้นคุณสามารถทำสิ่งต่อไปนี้ "ดังนั้นฉันลังเลที่จะทำเช่นเดียวกันสำหรับเว็บไซต์ Linux SE ด้วยเครื่องมือที่มาจาก Windows แต่นี่เป็นงานที่ดีที่แสดงให้เห็นถึงจุดแข็งของ PowerShell ค่อนข้างดีโดยไม่ต้องเชิญอาร์กิวเมนต์เก่าเกี่ยวกับการใช้คำฟุ่มเฟือย
Joey
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.