วิธีการจัดเรียงขนาดที่มนุษย์อ่านได้


11

โดยทั่วไปฉันกำลังมองหาไฟล์แล้วจัดเรียงตามขนาด สคริปต์ทำงานได้ถ้าฉันไม่จัดเรียงตามขนาดที่มนุษย์อ่านได้ แต่ฉันต้องการขนาดที่มนุษย์สามารถอ่านได้ ฉันจะจัดเรียงขนาดที่มนุษย์สามารถอ่านได้ได้อย่างไร

ตัวอย่างเช่น:

 ls -l | sort -k 5 -n | awk '{print $9 " " $5}'

ใช้งานได้ตามที่คาดหวังฉันมีขนาดไฟล์ของฉันเป็นไบต์จากน้อยไปมาก:

1.txt 1
test.txt 3
bash.sh* 573
DocGeneration.txt 1131
andres_stuff.txt 1465
Branches.xlsx 15087
foo 23735
bar 60566
2016_stuff.pdf 996850

ตอนนี้ฉันต้องการให้ขนาดที่มนุษย์อ่านได้ดังนั้นฉันจึงเพิ่มพารามิเตอร์ -h ลงใน ls และตอนนี้ไฟล์บางไฟล์ไม่เป็นระเบียบ:

 ls -lh | sort -k 5 -n | awk '{print $9 " " $5}'
1.txt 1
DocGeneration.txt 1.2K
andres_stuff.txt 1.5K
test.txt 3
Branches.xlsx 15K
foo 24K
bar 60K
bash.sh* 573
2016_stuff.pdf 974K


-k 5- มันทำงานอย่างไร
ctrl-alt-delor

@ ctrl-alt-delor: ฉันเชื่อว่าขนาดอยู่ในคอลัมน์ที่ 5 ของlsผลลัพธ์
jesse_b

2
การใช้duแทนที่จะlsเป็นความคิดที่ดี
xenoid

... หรือfind's -printfด้วย%pและ%sจัดรูปแบบ (ตามด้วย‘humanisation’ของขนาด)
Stephen Kitt

@Jesse_b ข้อผิดพลาดของฉันฉันเพิ่งสันนิษฐานว่าข้อมูลในคำถาม (ทำเครื่องหมายว่านี่คือสิ่งที่ฉันได้รับ) คืออินพุตที่เรียงลำดับฉันผิด
ctrl-alt-delor

คำตอบ:


28

ลอง sort -h k2

-h, - มนุษย์ - ตัวเลขเรียงลำดับเปรียบเทียบตัวเลขที่มนุษย์อ่านได้ (เช่น 2K 1G)

มันเป็นส่วนหนึ่งของ gnu sort, BSD sort และอื่น ๆ


5
ไม่ควรแยกวิเคราะห์ผลลัพธ์ที่lsควรหลีกเลี่ยง

3
@Tomasz ไม่เสมอไป หากมีการแสดงผลตามที่คุณต้องการการส่งไปยังการจัดรูปแบบอื่นจะไม่เป็นอันตรายโดยเฉพาะ สิ่งที่คุณไม่ควรทำคือวนซ้ำผลลัพธ์lsและใช้การวนรอบไฟล์โดยตรง การวนเวียนเพียงลำพังจะไม่ทำงานที่นี่ ที่กล่าวว่าฉันอาจจะชอบduสิ่งนี้
Bloodgain

1
@Bloodgain รูปแบบ ls ไม่รับประกันว่าจะเหมือนกันในระบบ / ls ไบนารีดังนั้นการแยกวิเคราะห์แบบพกพาจึงถือว่าเป็นไปไม่ได้
D. Ben Knoble

1
ชื่อไฟล์ที่มีช่องว่างจะทำให้สิ่งต่าง ๆ
สะดุดตา

1
@Bloodgain: files=(); for f in *; do [[ -L "$f" ]] && files+=("$f"); done; echo ${#files[@]}(ฉันอาจจะเป็นสวิตช์ทดสอบ symlink ผิด) หากคุณไม่สนใจ symlink files=(*); echo ${#files[@]}ซึ่งจะพกพาได้หากคุณใช้setและไม่ใช้อาร์เรย์
D. Ben Knoble

29

lsมีฟังก์ชันนี้ในตัวใช้-Sตัวเลือกและเรียงลำดับย้อนกลับ:ls -lShr

       -r, --reverse
              reverse order while sorting

       -S     sort by file size, largest first

1
-hไม่ใช่ตัวเลือกมาตรฐานlsแต่ต้องใช้งานได้ถ้า OP มีอยู่แล้ว ส่วนที่เหลือเป็นมาตรฐานและแน่นอนคำตอบที่ฉันจะเขียน
Toby Speight

5
1 lsจะไม่ยุ่งรอบแยกการส่งออกของ
David Richerby

นี่คือคำตอบที่ดีที่สุด แต่มันควรจะมีข้อมูลในการแสดงความคิดเห็น @ โทบี้: อาจจะไม่สามารถใช้ได้สำหรับคุณ-S lsFWIW, -Sได้รับการสนับสนุนแม้จะมีห้องสมุดของ Emacs ซึ่งจะใช้เมื่อระบบปฏิบัติการไม่เคยมีใครls-lisp.el lsมันทำงานใน Emacs บน MS Windows เช่น
Drew

นี่ควรเป็นคำตอบที่ยอมรับได้
กระจาย

1
@Drew: ความคิดเห็นของ Toby บอกว่า-hอาจไม่สามารถใช้ได้ในระดับสากล แต่ OP ก็ใช้งานมันอยู่แล้ว -Sจริงๆควรจะพร้อมใช้งานในระดับสากลเพราะมันอยู่ในการเชื่อมโยง POSIX ว่าโทบี้ให้ อย่างไรก็ตามมีชุดเครื่องมือที่ไม่ใช่ POSIX อยู่ไม่กี่ชุด
Kevin

5

เนื่องจากไม่มีการระบุเชลล์เฉพาะนี่คือวิธีทำทั้งหมดในzshเชลล์:

ls -lhf **/*(.Lk-1024oL)

**รูปแบบ glob ตรงเหมือน*แต่ข้าม/ใน pathnames คือเหมือนการค้นหา recursive จะทำ

lsคำสั่งจะทำให้ขนาดของมนุษย์ที่สามารถอ่านได้ด้วยและรูปแบบการออกรายการยาวด้วย-h พิการตัวเลือกการเรียงลำดับดังนั้นก็จะแสดงรายการไฟล์ในลำดับที่พวกเขาจะได้รับ-l-fls

คำสั่งนี้จัดเรียงตาม**/*(.Lk-1024oL)รูปแบบชื่อไฟล์ที่ทำให้กลมกลืนเพื่อให้ไฟล์มีขนาดเล็กลงก่อน **/*บิตตรงกับทุกไฟล์และไดเรกทอรีในไดเรกทอรีนี้และด้านล่าง แต่(...)ปรับเปลี่ยนพฤติกรรมของ glob (มันเป็น "glob รอบคัดเลือก")

มันคือoLจุดสิ้นสุดที่คำสั่งซื้อ ( o) ชื่อตามขนาดไฟล์ ( L"ความยาว")

.ที่เริ่มต้นทำให้ glob เท่านั้นตรงกับไฟล์ปกติ (ไม่ไดเรกทอรี)

Lk-1024ไฟล์บิตเลือกที่มีขนาดน้อยกว่า 1024 KB ( "ระยะเวลาใน KB น้อยกว่า 1024")

หากzshไม่ใช่เชลล์เชิงโต้ตอบหลักของคุณคุณสามารถใช้งานได้

zsh -c 'ls -lf **/*(.Lk-1024oL)'

ใช้setopt GLOB_DOTS(หรือzsh -o GLOB_DOTS -c ...) เพื่อจับคู่ชื่อที่ซ่อนไว้ด้วย ... หรือเพียงเพิ่มDในสตริงตัวระบุคุณสมบัติกลม


ขยายที่ด้านบนโดยสมมติว่าคุณต้องการเอาท์พุท 2 คอลัมน์พร้อมชื่อพา ธ และขนาดที่มนุษย์อ่านได้และยังสมมติว่าคุณมีnumfmtจาก coreutils ของ GNU

zmodload -F zsh/stat b:zstat

for pathname in **/*(.Lk-1024oL); do
    printf '%s\t%s\n' "$pathname" "$(zstat +size "$pathname" | numfmt --to=iec)"
done

หรือเร็วกว่า

paste <( printf '%s\n' **/*(.Lk-1024oL) ) \
      <( zstat -N +size **/*(.Lk-1024oL) | numfmt --to=iec )

4

หากคุณsortไม่มี-hตัวเลือกคุณสามารถใช้คำสั่ง awk (แม้ว่าจะยาวมาก) ดังต่อไปนี้:

find . -type f -size -1024k -exec ls -al {} \; | sort -k 5 -n | awk '{if ($5 > 1099511627776) {print $9,$5/1024/1024/1024/1024"T"} else if ($5 > 1073741824) {print $9,$5/1024/1024/1024"G"} else if ($5 > 1048576) {print $9,$5/1024/1024"M"} else if ($5 > 1024) {print $9,$5/1024"K"} else {print $9,$5"B"}}' | column -t

นี่จะเรียงลำดับผลลัพธ์ของคุณเป็นไบต์แล้วแปลงเป็นขนาดที่มนุษย์สามารถอ่านได้ในภายหลัง


-1

จะใช้งานได้ไหม

ls -l | awk '{if ($5<=1024) {print}}' | sort -k 5 -n | awk '{print $9"\t"substr($5/1024,1,3)"k"} '| column -t

awkexp แรกจะค้นหาไฟล์ที่น้อยกว่า 1M และอันที่สองจะใช้ขนาดไบต์จากผลลัพธ์และแปลงเป็น KB และพิมพ์องค์ประกอบ 3 ตัวแรกเพื่อให้ขนาดที่มนุษย์อ่านได้


ที่ไม่ได้แก้ปัญหา OPs - มันดูเฉพาะในไดเรกทอรีปัจจุบันและจะพิมพ์ไฟล์ปกติ จะเปรียบเทียบกับ 1Kb แทน 1MB ในที่สุดเราก็มาถึงคำตอบพร้อมคำอธิบายว่าทำไมรหัสจึงทำงาน
grochmal

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