จำนวนไฟล์ในแต่ละไดเรกทอรีย่อย


22

ฉันต้องการคำสั่ง BASH เพื่อแสดงรายการเฉพาะจำนวนไฟล์ในแต่ละไดเรกทอรีย่อยของไดเรกทอรี

เช่นในไดเรกทอรี/tmpมีdir1, dir2... ผมอยากจะดู:

`dir1` : x files 
`dir2` : x files ...

คำตอบ:


33

สมมติว่าคุณต้องการจำนวนไฟล์ที่เรียกซ้ำเท่านั้นไม่ใช่ไดเรกทอรีและประเภทอื่น ๆ สิ่งที่ควรทำ:

find . -maxdepth 1 -mindepth 1 -type d | while read dir; do
  printf "%-25.25s : " "$dir"
  find "$dir" -type f | wc -l
done

นอกจากนี้ฉันยังได้รับ "ค้นหา: คำเตือน: คุณได้ระบุตัวเลือก -maxdepth หลังจากอาร์กิวเมนต์ที่ไม่ใช่ตัวเลือก - ประเภท แต่ตัวเลือกไม่ได้ตำแหน่ง (-maxdepth ส่งผลกระทบต่อการทดสอบที่ระบุไว้ก่อนหน้านี้เช่นเดียวกับที่ระบุหลังจากนั้น) โปรดระบุตัวเลือก ก่อนข้อโต้แย้งอื่น ๆ "
jldupont

2
คำตอบทั้งสองที่ให้มาจะให้ผลลัพธ์ที่ไม่ถูกต้องในกรณีที่ไม่น่าเป็นไปได้ว่ามีไฟล์ที่ชื่อมีอักขระขึ้นบรรทัดใหม่ คุณสามารถจัดการกับมันด้วยfind... -print0 | xargs -0....
สกอตต์

@ jldupont: เลื่อนอาร์กิวเมนต์ความลึกก่อน ´-type d´ฉันได้แก้ไขคำตอบแล้ว
Thor

ใช่และขอฉันเพิ่มข้อมูลที่โซลูชันที่ยอดเยี่ยมนี้จะไม่ใช้ตัวแปรภายนอกใด ๆและจะทำงานร่วมกับbash alias!!
ไวยากรณ์

รวดเร็วและท่อsort -rn -k 2,2 -t$':'คุณจะได้รับรายชื่อ DESC
Andre Figueiredo

14

งานนี้ทำให้ฉันหลงใหลมากจนฉันอยากรู้วิธีแก้ปัญหาด้วยตัวเอง มันไม่ได้ใช้เวลาสักครู่และอาจเร็วกว่าในการประมวลผล ความพยายามของ Thor ช่วยให้ฉันมีความเข้าใจในรายละเอียดอย่างมาก

ดังนั้นนี่คือของฉัน:

find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "{} : $(find "{}" -type f | wc -l)" file\(s\)' \;

มันดูเรียบง่ายด้วยเหตุผลเพราะมีประสิทธิภาพมากกว่าที่คิด :-)

อย่างไรก็ตามหากคุณต้องการรวมสิ่งนี้ไว้ใน.bash_aliasesไฟล์ของคุณจะต้องมีลักษณะดังนี้:

alias somealias='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c '\''echo "{} : $(find "{}" -type f | wc -l)" file\(s\)'\'' \;'

สังเกตการจัดการคำพูดเดียวหลายระดับที่ยุ่งยากมาก และไม่เป็นไปไม่ได้ที่จะใช้เครื่องหมายคำพูดคู่สำหรับsh -cอาร์กิวเมนต์


ช้าลงเนื่องจากจะเรียกใช้ / bin / sh สำหรับแต่ละไดเรกทอรี strace -fc scriptคุณสามารถตรวจสอบเรื่องนี้ด้วย รุ่นของคุณใช้สายระบบมากขึ้นประมาณ 70% +1 สำหรับรหัสสั้น :-)
ธ อร์

1
แรงบันดาลใจจากสิ่งนี้ เรียงตามจำนวนไฟล์:find . -maxdepth 1 -mindepth 1 -type d -exec sh -c 'echo "$(find "{}" -type f | wc -l)" {}' \; | sort -nr
mnagel

7
find . -type f | cut -d"/" -f2 | uniq -c

แสดงรายการโฟลเดอร์และไฟล์ในโฟลเดอร์ปัจจุบันที่มีจำนวนไฟล์ที่พบใต้ IMO ที่รวดเร็วและมีประโยชน์ (ไฟล์ที่แสดงมีจำนวน 1)


1
คำอธิบายเล็ก ๆ น้อย ๆ เกี่ยวกับวิธีการทำงานของมัน? :)
C0deDaedalus

1
ยอดเยี่ยมขอบคุณ! คุณอาจต้องการเพิ่ม| sort -rnการเรียงลำดับย่อยตามจำนวนไฟล์
Dennis Golomazov

1

การใช้ find เป็นวิธีการที่แน่นอนหากคุณต้องการนับซ้ำ แต่ถ้าคุณต้องการนับจำนวนไฟล์โดยตรงภายใต้ไดเรกทอรีที่แน่นอน:

ls dir1 | wc -l


ฉันไม่ต้องการทำเช่นนี้สำหรับแต่ละไดเรกทอรี 1,000 รายการที่ฉันเคยไปที่นั่น ...
jldupont

จากนั้นใช้ xargs ls -d */ | xargs -n1 ls | wc -l(ใช้คำตอบที่คุณยอมรับถ้ามันใช้งานได้แล้ว! นี่เป็นเพียงและตอนนี้คุณรู้.)
jrajav

ข้อเสนอของคุณไม่แสดงผลลัพธ์ใด ๆ ในไม่กี่วินาทีในขณะที่คำตอบที่ฉันตอบรับได้
jldupont

@jrajav วิธีนี้ล้มเหลวอย่างยิ่งสำหรับไดเรกทอรีที่มีช่องว่างในนั้น นี่คือเหตุผลที่findสำคัญมาก (ให้อยู่คนเดียว-print0และxargs -0ชี้ออกไปแล้วจากสกอตต์ในคำตอบอื่น ๆ )
SyntaxError

1
find . -mindepth 1 -type d -print0 | xargs -0 -I{} sh -c 'printf "%4d : %s\n" "$(find {} -type f | wc -l)" "{}"'

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


0

สิ่งที่ฉันใช้ ... สิ่งนี้ทำให้อาร์เรย์ของไดเรกทอรีย่อยทั้งหมดในไดเรกทอรีที่คุณให้เป็นพารามิเตอร์ พิมพ์ไดเรกทอรีย่อยและจำนวนของไดเรกทอรีย่อยเดียวกันนั้นจนกว่าไดเรกทอรีย่อยทั้งหมดจะถูกประมวลผล

#!/bin/bash    
directories=($(/bin/ls -l $1 | /bin/grep "^d" | /usr/bin/awk -F" " '{print $9}'))

for item in ${directories[*]}
    do
        if [ -d "$1$item" ]; then
            echo "$1$item"
            /bin/ls $1$item | /usr/bin/wc -l
        fi
    done

0

คุณสามารถใช้รหัสหลามนี้ บูตล่ามโดยการเรียกใช้python3และวางสิ่งนี้:

folder_path = '.'
import os, glob
for folder in sorted(glob.glob('{}/*'.format(folder_path))):
    print('{:}: {:>8,}'.format(os.path.split(folder)[-1], len(glob.glob('{}/*'.format(folder)))))

หรือเวอร์ชันเรียกซ้ำสำหรับการนับซ้อน:

import os, glob
def nested_count(folder_path, level=0):
    for folder in sorted(glob.glob('{}/'.format(os.path.join(folder_path, '*')))):
        print('{:}{:}: {:,}'.format('    '*level, os.path.split(os.path.split(folder)[-2])[-1], len(glob.glob(os.path.join(folder, '*')))))
        nested_count(folder, level+1)
nested_count('.')

ตัวอย่างผลลัพธ์:

>>> figures: 5
>>> misc: 1
>>> notebooks: 5
>>>     archive: 65
>>>     html: 12
>>>     py: 12
>>>     src: 14
>>> reports: 1
>>>     content: 6
>>> src: 1
>>>     html_download: 1
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.