วิธีการรับขนาดไดเรกทอรีที่แท้จริง (จาก du)?


17

ฉันจะได้ขนาดไดเรกทอรีจริงโดยใช้เครื่องมือมาตรฐาน UNIX / Linux ได้อย่างไร

คำถามทางเลือก: ฉันจะดูขนาดไดเรกทอรีที่แท้จริงได้อย่างไร (ไม่ใช่การใช้ดิสก์)

เนื่องจากคนดูเหมือนจะมีคำจำกัดความที่แตกต่างกันของคำว่า "ขนาด": คำจำกัดความของฉันของ "ขนาดไดเรกทอรี" คือผลรวมของไฟล์ปกติทั้งหมดภายในไดเรกทอรีนั้น

ฉันไม่สนใจขนาดของ inode ของไดเร็กตอรี่หรืออะไรก็ตาม (ขนาดบล็อก * บล็อก) ที่ไฟล์ใช้ในระบบไฟล์ ไดเรกทอรีที่มี 3 ไฟล์ละ 1 ไบต์มีขนาดไดเรกทอรี 3 ไบต์ (ตามคำจำกัดความของฉัน)

การคำนวณขนาดไดเรกทอรีโดยใช้ du ดูเหมือนจะไม่น่าเชื่อถือ
ตัวอย่างเช่นmkdir foo && du -b fooรายงาน "4096 foo", 4096 ไบต์แทน 0 ไบต์ ด้วยไดเรกทอรีที่มีขนาดใหญ่มากขนาดไดเรกทอรีที่รายงานdu -hsสามารถปิดได้ 100 GB (!) และอื่น ๆ (ระบบไฟล์บีบอัด)

ดังนั้นจะต้องใช้อะไร (เครื่องมือ / ตัวเลือก) เพื่อให้ได้ขนาดไดเรกทอรีที่แท้จริง


ระบบไฟล์ใดบ้างที่ใช้ในตำแหน่งใหม่ - เป็นไปได้xfsหรือไม่?
Sergey Vlasov


และถ้า FS ใหม่ของคุณเป็นจริง XFS การใช้งานดิสก์เพิ่มขึ้นอย่างมากอาจเป็นเพราะpreallocation ก้าวร้าวซึ่งจะเป็นการลดการกระจายตัวของไฟล์ที่ค่าใช้จ่ายของการใช้งานดิสก์
Sergey Vlasov

คำตอบ:


8

นี่คือสคริปต์ที่แสดงขนาดไดเรกทอรีที่มนุษย์สามารถอ่านได้โดยใช้เครื่องมือมาตรฐาน Unix (POSIX)

#!/bin/sh
find ${1:-.} -type f -exec ls -lnq {} \+ | awk '
BEGIN {sum=0} # initialization for clarity and safety
function pp() {
  u="+Ki+Mi+Gi+Ti+Pi+Ei";
  split(u,unit,"+");
  v=sum;
  for(i=1;i<7;i++) {
    if(v<1024) break;
    v/=1024;
  }
  printf("%.3f %sB\n", v, unit[i]);
}
{sum+=$5}
END{pp()}'

เช่น:

$ ds ~        
72.891 GiB

และตอนนี้ฉันพบตัวเลือกอื่นที่หายไปในlsการเชิญที่แนะนำทั้งหมดที่นี่: -q. หากไม่มีตัวเลือกนี้สคริปต์จะหยุดทำงานหากชื่อไฟล์บางชื่อมีอักขระขึ้นบรรทัดใหม่ การเขียนเชลล์สคริปต์ที่เชื่อถือได้นั้นยากเกินไป…
Sergey Vlasov

@SergeyVlasov สคริปต์ที่ฉันโพสต์ไม่ควรแตกไฟล์ดังกล่าวเพียง แต่ละเว้นบรรทัดพิเศษเท่านั้น กรณีปัญหาเดียวที่จะเกิดขึ้นหากไฟล์ที่สร้างขึ้นมาอย่างระมัดระวังมีบรรทัดเพิ่มเติมที่มีเครื่องหมายโคลอนที่ห้าที่มีค่าตัวเลข ข้อเสนอแนะของคุณจะหลีกเลี่ยงสถานการณ์นั้นอย่างแน่นอน ขอบคุณสำหรับเคล็ดลับการอัปเดตสคริปต์
jlliagre

คำตอบที่ยอดเยี่ยม +1 ถึงคุณ
ehime

นี่เป็นหนึ่งในโซลูชั่นที่น่าเชื่อถือที่สุด มันทำงานกับชื่อไฟล์ที่มีช่องว่างหรือคำพูดในพวกเขาและมันจะพิมพ์ขนาดที่มนุษย์สามารถอ่านได้
basic6 6

@ KIAaze ขอบคุณสำหรับการตรวจสอบและแก้ไขรหัสของฉัน!
jlliagre

8

บางรุ่นduรองรับอาร์กิวเมนต์--apparent-sizeเพื่อแสดงขนาดที่ชัดเจนแทนการใช้ดิสก์ ดังนั้นคำสั่งของคุณจะเป็น:

du -hs --apparent-size

จากหน้า man สำหรับ du รวมอยู่ใน Ubuntu 12.04 LTS:

--apparent-size
      print apparent sizes,  rather  than  disk  usage;  although  the
      apparent  size is usually smaller, it may be larger due to holes
      in (`sparse') files, internal  fragmentation,  indirect  blocks,
      and the like

1
ไม่ทำงาน: รายงานที่ว่างสำหรับผู้ที่ว่างเปล่า
Karl Forner

1
สิ่งนี้ใช้ได้สำหรับฉัน
connorbode

2
มันมีขนาดแตกต่างกันอย่างมีนัยสำคัญเมื่อคุณเปรียบเทียบไดเรกทอรีในระบบไฟล์ที่แตกต่างกัน ตัวอย่างเช่นโฟลเดอร์เดียวกันมีขนาดที่ชัดเจนของ 290Gb บนระบบไฟล์ zfs และ exFat 324Gb การแก้ปัญหาข้างต้นมีขนาดเท่ากัน
Pixus.ru

4

เป็นทางเลือกโดยใช้ls:

ls -nR | grep -v '^d' | awk '{total += $5} END {print total, "Total"}'

ls -nR: -nlike -lแต่แสดงรายการ UID ที่เป็นตัวเลขและ GID และ -Rรายการไดเรกทอรีย่อยซ้ำ

grep -v:กลับความรู้สึกของการจับคู่เพื่อเลือกเส้นที่ไม่ตรงกัน (-v ถูกระบุโดย POSIX) '^ d'จะยกเว้นไดเรกทอรี

คำสั่ง Ls: http://linux.about.com/od/commands/l/blcmdl1_ls.htm

Man Grep: http://linux.die.net/man/1/grep

แก้ไข :

แก้ไขเป็นข้อเสนอแนะ @ Sergey Vlasov


การใช้-nตัวเลือกlsแทน-l(แสดงหมายเลข UID / GID แทนชื่อ) ปลอดภัยกว่าเพราะชื่อผู้ใช้และกลุ่มสามารถมีช่องว่างได้ (เช่นหากใช้winbindหรือsssdเข้าร่วมระบบกับโดเมน Windows คุณจะได้รับชื่อกลุ่มเช่นdomain users) . ควรเร็วขึ้นเนื่องจากไม่จำเป็นต้องค้นหาชื่อผู้ใช้และกลุ่ม
Sergey Vlasov

ขอบคุณนี่เร็วกว่าค้นหา -exec ls!
gpothier

4

สมมติว่าคุณมีduจาก coreutils ของ GNU คำสั่งนี้ควรคำนวณขนาดรวมทั้งหมดของจำนวนไฟล์โดยพลการภายในไดเรกทอรีโดยไม่มีข้อ จำกัด ใด ๆ กับจำนวนไฟล์:

find . -type f -print0 | du -scb --files0-from=- | tail -n 1

เพิ่ม-lตัวเลือกduหากมีไฟล์ฮาร์ดลิงก์บางไฟล์อยู่ภายในและคุณต้องการนับแต่ละฮาร์ดลิงก์แยกกัน (โดยค่าเริ่มต้นduจะนับฮาร์ดลิงก์หลายรายการเพียงครั้งเดียวเท่านั้น)

ความแตกต่างที่สำคัญที่สุดกับ plain du -sbคือ recursive duจะนับขนาดของไดเรกทอรีซึ่งมีการรายงานแตกต่างกันไปตามระบบไฟล์ที่แตกต่างกัน เพื่อหลีกเลี่ยงการนี้คำสั่งที่ใช้ในการส่งผ่านเฉพาะไฟล์ปกติเพื่อfind duความแตกต่างอีกอย่างก็คือว่า symlink นั้นจะถูกข้ามไป (หากพวกมันควรถูกนับfindคำสั่งควรถูกปรับ)

คำสั่งนี้จะใช้หน่วยความจำมากขึ้นกว่าธรรมดาdu -sbเพราะใช้--files0-from=FILEทำduอุปกรณ์และ inode เก็บตัวเลขของทุกไฟล์ประมวลผลเมื่อเทียบกับการทำงานเริ่มต้นของความทรงจำเท่านั้นไฟล์ที่มีการเชื่อมโยงอย่างหนักมากกว่าหนึ่ง (นี่ไม่ใช่ปัญหาหาก-lมีการใช้ตัวเลือกเพื่อนับจำนวนฮาร์ดลิงก์หลายครั้งเนื่องจากเหตุผลเดียวในการจัดเก็บอุปกรณ์และหมายเลขไอโหนดคือการข้ามไฟล์ฮาร์ดลิงก์ที่ได้รับการประมวลผลแล้ว)

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

find . -type f -print0 | du -scbh --files0-from=- | tail -n 1

หรือ (หากคุณกังวลว่าเอฟเฟกต์บางอย่าง-bจะถูกแทนที่ด้วย-h)

find . -type f -print0 | du -sc --apparent-size -h --files0-from=- | tail -n 1

ไม่แน่ใจว่าจะทำอย่างไรกับ FreeBSD - แม้ว่า-bอาจจะถูกแทนที่ด้วย-A -B 1ก็ไม่เทียบเท่า--files0-from=-และการใช้xargsจะต้องมีวิธีแก้ไขปัญหาบางอย่างในกรณีที่รายการไฟล์มีขนาดใหญ่กว่าARG_MAX(และโซลูชันภายนอกสำหรับเอาต์พุตที่มนุษย์อ่านได้)
Sergey Vlasov

3

หากสิ่งที่คุณต้องการคือขนาดของไฟล์ยกเว้นพื้นที่ที่ไดเรกทอรีใช้งานคุณสามารถทำสิ่งต่าง ๆ ได้

find . -type f -print0 | xargs -0 du -scb | tail -n 1

@SergeyVlasov argmaxชี้ให้เห็นว่าเรื่องนี้จะล้มเหลวถ้าคุณมีไฟล์มากกว่า เพื่อหลีกเลี่ยงการใช้สิ่งที่ต้องการ:

find . -type f -exec du -sb '{}' \; | gawk '{k+=$1}END{print k}'

1
คำสั่งนี้จะส่งผลที่ไม่ถูกต้องหากไดเรกทอรีมีไฟล์จำนวนมากที่ไฟล์เหล่านั้นไม่พอดีกับขนาดอาร์กิวเมนต์ของ execve () - ในกรณีนี้xargsจะเรียกใช้duหลายครั้งและการร้องขอแต่ละครั้งจะพิมพ์ผลรวมทั้งหมดสำหรับส่วนของมัน จากรายการไฟล์ทั้งหมดจากนั้นtailจะแสดงเพียงขนาดรวมของส่วนสุดท้าย
Sergey Vlasov

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