สถิติแบบเรียกซ้ำในประเภทไฟล์ในไดเรกทอรี?


65

ฉันขูดเว็บไซต์สำหรับโครงการแปลง ฉันต้องการทำสถิติเกี่ยวกับประเภทของไฟล์ในนั้นเช่น 400 .htmlไฟล์ 100 ไฟล์.gifฯลฯ วิธีง่ายๆในการทำเช่นนี้คืออะไร? มันจะต้องเกิดซ้ำ

แก้ไข:ด้วยสคริปต์ที่ maxschelpzig โพสต์ฉันมีปัญหาเนื่องจากสถาปัตยกรรมของเว็บไซต์ที่ฉันได้คัดลอกมา ไฟล์บางไฟล์เป็นชื่อที่*.php?blah=blah&foo=barมีอาร์กิวเมนต์ต่าง ๆ ดังนั้นจึงนับว่าเป็นไฟล์ที่ไม่ซ้ำกัน ดังนั้นการแก้ปัญหาจะต้องพิจารณาว่า*.php*เป็นประเภทเดียวกันทั้งหมดเพื่อที่จะพูด

คำตอบ:


96

คุณสามารถใช้findและuniqสำหรับสิ่งนี้เช่น:

$ find . -type f | sed 's/.*\.//' | sort | uniq -c
   16 avi
   29 jpg
  136 mp3
    3 mp4

คำอธิบายคำสั่ง

  • find พิมพ์ชื่อไฟล์ทั้งหมดซ้ำ ๆ ซ้ำ
  • sed ลบทุกชื่อไฟล์คำนำหน้าจนกระทั่งนามสกุลไฟล์
  • uniq ถือว่าอินพุตเรียงลำดับ
    • -c ทำการนับ (เช่นฮิสโตแกรม)

ฉันมีสคริปต์ที่คล้ายกัน ง่ายและรวดเร็ว
Rufo El Magufo

ไฟล์บางไฟล์เป็นชื่อที่*.php?blah=blah&foo=barมีอาร์กิวเมนต์ต่าง ๆ ดังนั้นจึงนับว่าเป็นไฟล์ที่ไม่ซ้ำกัน ฉันจะแก้ไขเพื่อค้นหาได้*.php*อย่างไร
user394

3
คุณสามารถลองใช้นิพจน์นิพจน์อื่นเช่นsed 's/^.*\(\.[a-zA-Z0-9][a-zA-Z0-9][a-zA-Z0-9]\).*$/\1/'
maxschlepzig

ขอบคุณที่สละเวลาอธิบายว่าแต่ละส่วนทำอะไร คำตอบมากมายในหัวข้อที่คล้ายกันข้ามส่วนนี้ / learning-to-fish
MechEthan

1
@ bela83 ตัวแปรลูกพรุนใช้การประเมินผลแบบลัดวงจรดังนั้นเวอร์ชันแรกของฉันfind -name '.*' -prune -o -type f -printประเมินเช่น: ถ้ารายการไดเรกทอรีตรงกัน.*แล้วตัดมันมิฉะนั้นถ้าเป็นไฟล์ให้พิมพ์ออกมา เนื่องจาก.*ยังมีการจับคู่.เช่น CWD ทุกอย่างจะถูกตัดเช่นการค้นหาไม่ได้ลงไปในไดเรกทอรีแรก บางทีรุ่นเก่า 2 ปีของfindพฤติกรรมแตกต่างกัน - หรือมันเป็นเพียงการกำกับดูแลของฉันกลับมาแล้ว อย่างไรก็ตามfind -name '.*' -not -name . -prune -o -type f -printแก้ไขสิ่งนี้
maxschlepzig

6

ด้วย zsh:

print -rl -- **/?*.*(D.:e) | uniq -c |sort -n

รูปแบบที่ **/?*.*ตรงกับไฟล์ทั้งหมดที่มีส่วนขยายในไดเรกทอรีปัจจุบันและไดเรกทอรีย่อยซ้ำ ตัวระบุแบบหมุนวน Dอนุญาตให้ทำการzshสำรวจแม้กระทั่งไดเร็กทอรีที่ซ่อนอยู่และพิจารณาไฟล์ที่ซ่อนอยู่.เลือกเฉพาะไฟล์ปกติ ปรับปรุงประวัติศาสตร์ยังคงมีเพียงส่วนขยายของแฟ้ม print -rlพิมพ์หนึ่งคู่ต่อบรรทัด uniq -cนับรายการที่เหมือนกันติดต่อกัน (ผลลัพธ์ glob ถูกเรียงลำดับแล้ว) การโทรครั้งสุดท้ายเพื่อsortเรียงลำดับส่วนขยายตามจำนวนการใช้


5

ซับเดี่ยวนี้ดูเหมือนว่าจะเป็นวิธีที่แข็งแกร่งพอสมควร:

find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$/\1/p' | sort | uniq -c

find . -type f -printf '%f\n'พิมพ์ basename ของไฟล์ปกติทุกคนในต้นไม้กับไดเรกทอรีไม่มี ที่ไม่ต้องกังวลเกี่ยวกับไดเรกทอรีที่อาจมี.อยู่ในพวกเขาในsedregex ของคุณ

sed -r -n 's/.+(\..*)$/\1/p'แทนที่ชื่อไฟล์ที่เข้ามามีเพียงการขยาย เช่นจะกลายเป็น.somefile.ext .extหมายเหตุเริ่มต้น.+ใน regex; ผลนี้ในการแข่งขันใด ๆ .ต้องอย่างน้อยหนึ่งตัวก่อนของส่วนขยาย สิ่งนี้จะป้องกันไม่ให้ชื่อไฟล์เหมือน.gitignoreถูกมองว่าไม่มีชื่อเลยและนามสกุล '.gitignore' ซึ่งอาจเป็นสิ่งที่คุณต้องการ ถ้าไม่ได้แทนที่ด้วย.+.*

ส่วนที่เหลือของสายมาจากคำตอบที่ได้รับการยอมรับ

แก้ไข : หากคุณต้องการฮิสโตแกรมที่เรียงลำดับอย่างดีในรูปแบบแผนภูมิ Paretoเพียงเพิ่มอีกหนึ่งsortส่วนท้าย:

find . -type f -printf '%f\n' | sed -r -n 's/.+(\..*)$/\1/p' | sort | uniq -c | sort -bn

เอาต์พุตตัวอย่างจากแผนผังซอร์ส Linux ที่สร้างขึ้น:

    1 .1992-1997
    1 .1994-2004
    1 .1995-2002
    1 .1996-2002
    1 .ac
    1 .act2000
    1 .AddingFirmware
    1 .AdvancedTopics
    [...]
 1445 .S
 2826 .o
 2919 .cmd
 3531 .txt
19290 .h
23480 .c

1

ฉันได้ใส่ bash script ไว้ใน~/binโฟลเดอร์ของฉันซึ่งexhistมีเนื้อหานี้:

#!/bin/bash

for d in */ ; do
        echo $d
        find $d -type f | sed -r 's/.*\/([^\/]+)/\1/' | sed 's/^[^\.]*$//' | sed -r 's/.*(\.[^\.]+)$/\1/' | sort | uniq -c | sort -nr
#       files only      | keep filename only          | no ext -> '' ext   | keep part after . (i.e. ext) | count          | sort by count desc
done

ไม่ว่าฉันจะอยู่ในไดเรกทอรีใดฉันเพิ่งพิมพ์ 'exh' แท็บทำการเติมให้โดยอัตโนมัติและฉันเห็นสิ่งนี้:

$ exhist
src/
      7 .java
      1 .txt
target/
     42 .html
     10 .class
      4 .jar
      3 .lst
      2 
      1 .xml
      1 .txt
      1 .properties
      1 .js
      1 .css

ป.ล. การตัดส่วนหลังเครื่องหมายคำถามควรเป็นเรื่องง่ายที่จะทำกับคำสั่ง sed อื่นที่อาจเกิดขึ้นหลังจากคำสั่งสุดท้าย (ฉันไม่ได้ลอง): sed 's/\?.*//'

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.