ค้นหาขนาดทั้งหมดของไฟล์บางไฟล์ภายในสาขาไดเรกทอรี


140

สมมติว่ามีไดเรกทอรีที่เก็บรูปภาพพูด./photos/john_doeภายในนั้นมีหลายไดเรกทอรีย่อยที่มีไฟล์บางไฟล์อยู่ (พูด*.jpg) ฉันจะคำนวณขนาดสรุปของไฟล์เหล่านั้นใต้john_doeสาขาได้อย่างไร

ฉันพยายามdu -hs ./photos/john_doe/*/*.jpgแต่มันแสดงเฉพาะไฟล์แต่ละไฟล์เท่านั้น นอกจากนี้ติดตามเพียงระดับแรกรังของjohn_doeไดเรกทอรีเช่นแต่ข้ามjohn_doe/june/john_doe/june/outrageous/

ดังนั้นฉันจะสำรวจทั้งสาขาได้อย่างไรรวมขนาดของไฟล์ที่แน่นอน?

คำตอบ:


183
find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$

หากต้องการมากกว่าหนึ่งการร้องขอduเนื่องจากรายการไฟล์มีความยาวมากจะมีการรายงานผลรวมจำนวนมากและต้องสรุปผล


7
ค้นหา -iname 'file *' -exec du -cb {} + | grep รวม $ | ตัด -f1 | paste -sd + - | bc # summed size byte
Michal Čizmazia

3
หากระบบของคุณทำงานภายใต้ภาษาอื่นคุณต้องเปลี่ยนยอดรวม $ เป็นคำอื่น ๆ เช่น razem $ ในภาษาโปแลนด์
Zbyszek

1
คุณสามารถเพิ่มLC_ALL=POSIXคำนำหน้าให้ grep รวมเป็นเช่นนี้ได้เสมอ:LC_ALL=POSIX find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$
Sven

2
หากคุณไม่ได้ใช้งาน-nameให้เปลี่ยน grep เป็นgrep -P "\ttotal$"มิฉะนั้นจะทำการจับไฟล์ทั้งหมดที่ลงท้ายด้วย "ทั้งหมด" เช่นกัน
thdoan

3
@ MichalČizmaziaเชลล์บางตัว (เช่น Git Bash สำหรับ Windows) ไม่ได้มาด้วยbcดังนั้นนี่เป็นวิธีแก้ปัญหาแบบพกพาที่มากขึ้น:find -name '*.jpg' -type f -exec du -bc {} + | grep total$ | cut -f1 | awk '{ total += $1 }; END { print total }'
thdoan

50
du -ch public_html/images/*.jpg | grep total
20M total

ให้การใช้งานทั้งหมดกับ.jpgไฟล์ของฉันในไดเรกทอรีนี้

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

คุณอาจพบว่าตัวอย่างคำสั่ง duมีประโยชน์ (รวมถึงfind)


2
สิ่งนี้ไม่ได้ข้ามไดเรกทอรีพื้นฐานหรือไม่
mbaitoff

วิธีนี้ง่ายกว่าการพิมพ์โซลูชันที่ยอมรับ แต่เพียงครึ่งเดียวเท่านั้นจะไม่รวมรูปภาพในไดเรกทอรีย่อย ดีที่จะรู้ว่าไฟล์ทั้งหมดอยู่ในไดเรกทอรีเดียว
gbmhunter

@gbmhunter ฉันคิดว่าถ้าคุณเพิ่มพารามิเตอร์ -R ใน -ch คุณจะได้รับไดเรกทอรีย่อยตามที่มันวนซ้ำทรีไดเรกทอรี ขณะนี้ฉันไม่ได้อยู่ที่คอมพิวเตอร์เพื่อทดลองใช้เพื่อยืนยัน
Levon

1
ผมไม่เห็น-Rตัวเลือกที่man7.org/linux/man-pages/man1/du.1.html และผมไม่คิดว่าเป็นตัวเลือกที่ recursive จะช่วยในกรณีนี้เพราะเปลือกจะทำการขยายตัว glob duก่อนที่จะผ่านข้อโต้แย้งที่จะ
gbmhunter

22

ในขั้นต้นคุณต้องการสองสิ่ง:

du -ch -- **/*.jpg | tail -n 1

คำตอบที่ดีมาก เรียบง่ายกว่าการใช้การค้นหา (ตราบใดที่ * หรือ ** ตรงกับโครงสร้างไดเรกทอรี)
Andre de Miranda

นอกจากนี้ยังสามารถจัดการรายการไฟล์ที่ยาวมาก ๆ ในขณะที่การใช้findสามารถส่งคืนผลลัพธ์ที่ผิดพลาดได้
Eric Fournie

การขยาย bash brace ช่วยให้สามารถวัด wildcard หลายชุดได้เช่นกัน du -ch -- ./{dir1,dir2}/*.jpgหรือdu -ch -- ./{prefix1*,prefix2*}.jpg
J.Money

@EricFournie อย่างไรก็ตามฉันพบArgument list too longข้อผิดพลาดเมื่อประมวลผลไฟล์ข้อความประมาณ 300k
xtluo

จำนวนอาร์กิวเมนต์สูงสุดสำหรับคำสั่ง (ในกรณีนี้ชื่อไฟล์ที่ส่งคืนโดยการขยายไวด์การ์ด) สามารถตรวจสอบgetconf ARG_MAXได้ หากคุณมีมากกว่านั้นคุณจะต้องประมวลผลไฟล์ทีละไฟล์หรือเป็นชุดพร้อมลูปสำหรับลูป
Eric Fournie

17

คำตอบที่ดีที่สุดคือ:

{ find <DIR> -type f -name "*.<EXT>" -printf "%s+"; echo 0; } | bc

และรุ่นที่เร็วกว่านั้นไม่ จำกัด โดย RAM แต่ต้องใช้ GNU AWK พร้อมการรองรับ bignum:

find <DIR> -type f -name "*.<EXT>" -printf "%s\n" | gawk -M '{t+=$1}END{print t}'

รุ่นนี้มีคุณสมบัติดังต่อไปนี้:

  • ความสามารถทั้งหมดของfindเพื่อระบุไฟล์ที่คุณต้องการ
  • รองรับไฟล์นับล้าน
    • คำตอบอื่น ๆ ที่นี่ถูก จำกัด โดยความยาวสูงสุดของรายการอาร์กิวเมนต์
  • วางไข่เพียง 3 ขั้นตอนง่าย ๆ ด้วยทรูพุตที่น้อยที่สุด
    • คำตอบมากมายที่นี่วางไข่กระบวนการ C + N โดยที่ C คือค่าคงที่และ N คือจำนวนไฟล์
  • ไม่รำคาญกับการจัดการสตริง
    • รุ่นนี้ไม่ทำการ grepping หรือ regexing
    • ทีนี้, findการจับคู่ไวด์การ์ดแบบง่ายของชื่อไฟล์
  • เลือกรูปแบบรวมในรูปแบบมนุษย์สามารถอ่านได้ (เช่น. 5.5K, 176.7M, ... )
    • เพื่อทำสิ่งนั้นต่อท้าย | numfmt --to=si

ฉันชอบความเรียบง่ายของคำตอบนี้แม้ว่าจะใช้ได้กับฉันเท่านั้นเมื่อฉันแนะนำช่องว่างหลังจากเปิดวงเล็บปีกกาและก่อนปิดวงเล็บปีกกา ฉันสงสัยว่ามันจะรองรับจำนวนไฟล์ 'infiinte' หรือไม่ :)
andyb

1
@andyb ขอบคุณสำหรับคำติชมต้องใช้ช่องว่างรอบวงเล็บปีกกาใน BASH ฉันใช้ ZSH ดังนั้นฉันจึงไม่สังเกตเห็นว่า และจำนวนไฟล์ถูก จำกัด โดย RAM ที่มีอยู่ในระบบของคุณเนื่องจากการใช้หน่วยความจำของ bc เติบโตช้าลงเมื่อตัวเลขไหลเข้ามา
Jan Chren - rindeal

8

คำตอบที่ได้รับจนถึงขณะนี้ไม่ได้คำนึงว่ารายชื่อไฟล์ที่ส่งผ่านจากหา du อาจจะยาวเพื่อให้พบโดยอัตโนมัติแยกรายการเป็นชิ้นที่มีผลในหลาย ๆ totalที่ปรากฏของ

คุณสามารถgrep total(locale!) และรวมด้วยตนเองหรือใช้คำสั่งอื่น AFAIK มีเพียงสองวิธีในการรับผลรวมทั้งหมด (เป็นกิโลไบต์) ของไฟล์ทั้งหมดที่พบโดย find:
find . -type f -iname '*.jpg' -print0 | xargs -r0 du -a| awk '{sum+=$1} END {print sum}'

คำอธิบาย
find . -type f -iname '*.jpg' -print0: ค้นหาไฟล์ทั้งหมดที่มีนามสกุล jpg โดยไม่คำนึงถึงตัวพิมพ์เล็ก (เช่น * .jpg, * .JPG, * .Jpg ... ) และส่งออก (สิ้นสุดด้วย null)
xargs -r0 du -a: -r: Xargs จะเรียกคำสั่งแม้ไม่มีการส่งผ่านอาร์กิวเมนต์ซึ่ง -r ป้องกัน -0 หมายถึงสตริงที่สิ้นสุดด้วยค่า null (ไม่ใช่การขึ้นบรรทัดใหม่)
awk '{sum+=$1} END {print sum}': สรุปขนาดไฟล์ที่ส่งออกโดยคำสั่งก่อนหน้า

และสำหรับการอ้างอิงวิธีอื่นจะเป็น
find . -type f -iname '*.jpg' -print0 | du -c --files0-from=-


คำแนะนำเพิ่มเติม: บน HDD ของฉันที่มีไฟล์ 23428 (22323 เป็นภาพ) วิธีแรกใช้เวลา 1 วินาทีในขณะที่อีกอันที่สองทำงาน 3.8 วินาที
ม.ค.

โปรดทราบว่าทั้งคู่ถือว่าระบบ GNU ชื่อแรกสมมติว่าชื่อไฟล์ไม่มีอักขระขึ้นบรรทัดใหม่
Stéphane Chazelas

ฉันพนันได้เลยว่าจะdu --file0-fromใช้เวลานานกว่าเพราะคุณรันก่อน (เอฟเฟกต์การแคช)
Stéphane Chazelas

ด้วยอาจมีxargsหลายdu -aรันดังนั้นคุณอาจมีความแตกต่างหากมีการเชื่อมโยงอย่างหนัก
Stéphane Chazelas

3

หากรายการไฟล์มีขนาดใหญ่เกินไปที่ไม่สามารถส่งผ่านไปยังการเรียกใช้ครั้งเดียวdu -cในระบบ GNU คุณสามารถทำได้:

find . -iname '*.jpg' -type f -printf '%b\t%D:%i\n' |
  sort -u | cut -f1 | paste -sd+ - | bc

(ขนาดที่แสดงเป็นบล็อก 512 ไบต์) เหมือนduจะพยายามนับลิงก์ที่ยากเพียงครั้งเดียว หากคุณไม่สนใจเรื่องลิงก์คุณสามารถทำให้มันง่ายขึ้นไปที่:

(printf 0; find . -iname '*.jpg' -type f -printf +%b) | bc

หากคุณต้องการขนาดแทนการใช้ดิสก์แทนที่ด้วย%b %sขนาดจะถูกแสดงเป็นไบต์


-bash: bc: command not foundCentos - Linux 2.6.32-431.el6.x86_64
yeya

@yeya ดูเหมือนว่าการปรับใช้ CentOS ของคุณจะใช้งานไม่ได้ bcเป็นคำสั่ง POSIX ที่ไม่จำเป็น
Stéphane Chazelas

1

วิธีแก้ปัญหาที่กล่าวถึงยังไม่มีประสิทธิภาพ (exec มีราคาแพง) และต้องการงานเพิ่มเติมด้วยตนเองเพื่อหาผลรวมหากรายการไฟล์ยาวหรือไม่ทำงานบน Mac OS X วิธีแก้ปัญหาต่อไปนี้รวดเร็วมากควรทำงานกับระบบใดก็ได้และ ให้ผลรวมคำตอบเป็น GB (ลบ a / 1024 ถ้าคุณต้องการดูผลรวมเป็น MB): find . -iname "*.jpg" -ls |perl -lane '$t += $F[6]; print $t/1024/1024/1024 . " GB"'


ทั้ง-inameมิได้-lsเป็นมาตรฐาน / แบบพกพาดังนั้นมันจะไม่ทำงานในระบบใดอย่างใดอย่างหนึ่ง มันจะไม่ทำงานอย่างถูกต้องหากมีชื่อไฟล์หรือเป้าหมาย symlink ที่มีอักขระขึ้นบรรทัดใหม่
Stéphane Chazelas

โปรดทราบด้วยว่าจะให้ผลรวมของขนาดไฟล์ไม่ใช่การใช้งานดิสก์ สำหรับ symlink จะให้ขนาดของ symlink ไม่ใช่ไฟล์ที่ชี้ไป
Stéphane Chazelas

1

การปรับปรุงคำตอบที่ยอดเยี่ยมของ SHW เพื่อให้ทำงานกับสถานที่ใด ๆ เช่น Zbyszek ชี้ให้เห็นในความคิดเห็นของเขา:

LC_ALL=C find ./photos/john_doe -type f -name '*.jpg' -exec du -ch {} + | grep total$

1

โดยธรรมชาติแล้วลำดับชั้นไดเรกทอรีและ awk สามารถทำการกรองดังนั้นสิ่งนี้อาจจะเพียงพอ:

du -ak | awk 'BEGIN {sum=0} /\.jpg$/ {sum+=$1} END {print sum}'

สิ่งนี้ทำงานโดยไม่มี GNU


1
สิ่งนี้มีราคาแพงกว่าเนื่องจากมีการstatเรียกไฟล์ที่ไม่สอดคล้องกับรูปแบบการค้นหา
Law29

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