ฉันจะรับขนาดไฟล์ในสคริปต์ทุบตีได้อย่างไร


246

ฉันจะรับขนาดไฟล์ในสคริปต์ทุบตีได้อย่างไร

ฉันจะกำหนดสิ่งนี้ให้กับตัวแปร bash ได้อย่างไรเพื่อใช้ในภายหลัง



1
จับคู่นี้กับpvและcatสำหรับคำสั่งคัดลอกที่แสดงความคืบหน้าและ ETA :)
sudo

stat -c% s file.name
neverMind9

คำตอบ:


242

ทางออกที่ดีที่สุดของคุณหากอยู่ในระบบ GNU:

stat --printf="%s" file.any

จากผู้ชายสถิติ :

ขนาดรวม% s หน่วยเป็นไบต์

ในสคริปต์ทุบตี:

#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."

หมายเหตุ: ดูคำตอบของ @ chbrownสำหรับวิธีใช้ stat ในเทอร์มินัลบน Mac OS X


7
@ haunted85 statเป็นวิธีที่ตรงไปตรงมาที่สุดโดยสมมติว่าคุณใช้ Linux หรือ Cygwin ( statไม่ใช่มาตรฐาน) wc -cตามที่แนะนำโดยEugéneเป็นแบบพกพา
Gilles

2
stat: illegal option -- c
Iulian Onofrei

stat --printf="%s" file.txtได้ทำอะไรเลยไม่เอาท์พุทใน Debian เจสซี ...
woohoo

5
ใน MacOS งานนี้:stat -f%z myfile.tar
ccpizza

2
@woohoo พรอมต์ของคุณเขียนทับเอาต์พุต man statกล่าวว่า --printf ละเว้นการขึ้นบรรทัดใหม่ ใช้--formatหรือ-cเพื่อดูผลลัพธ์ รับข้อมูลเชิงลึกมากขึ้นโดยเปรียบเทียบstat --printf="%s" file.any | xxd -กับstat -c "%s" file.any | xxd -
หลาน

92
file_size_kb=`du -k "$filename" | cut -f1`

ปัญหาเกี่ยวกับการใช้statคือมันเป็นส่วนขยาย GNU (Linux) du -kและcut -f1มีการระบุโดย POSIX และดังนั้นจึงพกพาไปยังระบบ Unix ใด ๆ

Solaris, ตัวอย่างเช่นมาพร้อมกับทุบตี statแต่ไม่ได้มี นี่ไม่ใช่สมมุติทั้งหมด

lsมีปัญหาที่คล้ายกันซึ่งไม่ได้ระบุรูปแบบที่แน่นอนของเอาต์พุตดังนั้นการวิเคราะห์เอาต์พุตจึงไม่สามารถทำได้แบบพกพา du -hยังเป็นส่วนขยายของ GNU

ยึดติดกับโครงสร้างแบบพกพาหากเป็นไปได้และคุณจะทำให้ชีวิตของใครบางคนง่ายขึ้นในอนาคต อาจเป็นของคุณเอง


48
duไม่ได้ให้ขนาดของไฟล์มันแสดงให้เห็นว่ามีการใช้พื้นที่ไฟล์มากน้อยเพียงใดซึ่งแตกต่างอย่างละเอียด (โดยปกติแล้วขนาดที่รายงานduคือขนาดของไฟล์จะถูกปัดเศษขึ้นเป็นจำนวนบล็อกที่ใกล้ที่สุดโดยที่บล็อก โดยทั่วไปแล้วจะเป็น 512B หรือ 1kB หรือ 4kB)
Gilles

7
@Gilles ไฟล์ที่กระจัดกระจาย (เช่นไฟล์ที่มีรูอยู่) รายงานน้อยกว่าความยาว
vonbrand

5
นี้ด้วย--bytesหรือ-bแทน-kควรจะเป็นคำตอบที่ได้รับการยอมรับ
Amedee Van Gasse

1
-h( "มนุษย์") ตัวเลือกในการduจะผลิตคำตอบที่เหมาะสมที่สุดสำหรับกรณีทั่วไป: file_size=`du -h "$filename" | cut -f1เป็นมันจะแสดง K (กิโลไบต์), M (เมกะไบต์) หรือ G (กิกะไบต์) ตามความเหมาะสม
fralau

1
@fralau: OP ต้องการ "กำหนดสิ่งนี้ให้กับตัวแปร bash เพื่อให้สามารถใช้ในภายหลัง" ดังนั้นจึงมีความเป็นไปได้มากกว่าที่พวกเขาต้องการค่าตัวเลขจริงไม่ใช่การประมาณที่มนุษย์สามารถอ่านได้ นอกจากนี้ยัง-hเป็นส่วนขยายของ GNU มันไม่ได้มาตรฐาน
Nemo

74

คุณสามารถใช้คำสั่ง "นับจำนวนคำ" ( wc):

wc -c "$filename" | awk '{print $1}'

ปัญหาwcคือมันจะเพิ่มชื่อไฟล์และเยื้องออก ตัวอย่างเช่น:

$ wc -c somefile.txt
    1160 somefile.txt

หากคุณต้องการหลีกเลี่ยงการโยงภาษาที่ถูกตีความหรือตัวแก้ไขสตรีมเพื่อให้ได้ขนาดไฟล์ให้เปลี่ยนเส้นทางอินพุตจากไฟล์เพื่อwcไม่ให้เห็นชื่อไฟล์:

wc -c < "$filename"

แบบฟอร์มสุดท้ายนี้สามารถใช้กับการทดแทนคำสั่งเพื่อจับค่าที่คุณต้องการเป็นตัวแปรเชลล์ได้อย่างง่ายดายตามที่Gillesระบุไว้ด้านล่าง

size="$(wc -c <"$filename")"

30
wc -c <"$FILENAME"ให้มีขนาดที่ไม่มี cruft อื่น ๆ size=$(wc -c <"$FILENAME")จึง
Gilles

6
อีกจุดหนึ่ง: ฉันเพิ่งทดสอบและwc -c < fileดูเหมือนว่าจะเร็วมากอย่างน้อยใน OS X ฉันเดาว่า wc มีสมองที่จะลองจัดเก็บไฟล์หากระบุ -c ไว้เท่านั้น
Edward Falk

4
@EdwardFalk: GNU wc -cใช้fstatแต่จากนั้นค้นหาบล็อกสุดท้ายของไฟล์และอ่านst_blksizeไบต์สูงสุดล่าสุด เห็นได้ชัดว่าเป็นเพราะไฟล์ใน Linux /procและ/sysตัวอย่างมีขนาดสถิติที่เป็นค่าโดยประมาณเท่านั้นและwcต้องการรายงานขนาดจริงไม่ใช่ขนาดสถิติที่รายงาน ฉันคิดว่ามันคงจะแปลกสำหรับwc -cการรายงานขนาดที่แตกต่างกว่าwcแต่ไม่ควรอ่านข้อมูลจากไฟล์ถ้ามันเป็นไฟล์ดิสก์ปกติและไม่ใช่ในหน่วยความจำ หรือการจัดเก็บเทปที่เลวร้ายยิ่งใกล้เส้น ...
ปีเตอร์ Cordes

1
ดูเหมือนว่าprintfยังคงเห็นการเยื้องเช่น->printf "Size: $size" size: <4 spaces> 54339ในทางกลับกันechoช่องว่างไม่สนใจ มีวิธีใดที่จะทำให้มันสอดคล้องกัน?
Eugene Kulabuhov

2
@keithpjolley: fstatโดยการเรียก ลองใช้strace wc -c </etc/passwdและคุณจะเห็นสิ่งที่กำลังทำ
Nemo

48

BSD's (Mac OS X's) statมีการตั้งค่าสถานะอาร์กิวเมนต์รูปแบบที่แตกต่างกันและตัวระบุฟิลด์ที่แตกต่างกัน จากman stat(1):

  • -f format: แสดงข้อมูลโดยใช้รูปแบบที่ระบุ ดูส่วน FORMATS สำหรับคำอธิบายของรูปแบบที่ถูกต้อง
  • ... ส่วนรูปแบบ ...
  • z: ขนาดของไฟล์เป็นไบต์

ดังนั้นทั้งหมดเข้าด้วยกันตอนนี้:

stat -f%z myfile1.txt

28

ขึ้นอยู่กับสิ่งที่คุณหมายถึงขนาด

size=$(wc -c < "$file")

จะให้จำนวนไบต์ที่สามารถอ่านได้จากไฟล์ IOW มันคือขนาดของเนื้อหาของไฟล์ อย่างไรก็ตามมันจะอ่านเนื้อหาของไฟล์ (ยกเว้นว่าไฟล์เป็นไฟล์ปกติหรือ symlink ไปยังไฟล์ปกติในwcการปรับใช้ส่วนใหญ่เป็นการปรับให้เหมาะสม) ที่อาจมีผลข้างเคียง ตัวอย่างเช่นสำหรับไปป์ที่มีชื่อสิ่งที่ถูกอ่านไม่สามารถอ่านได้อีกต่อไปและสำหรับสิ่งที่ชอบ/dev/zeroหรือ/dev/randomขนาดที่ไม่มีที่สิ้นสุดมันจะต้องใช้เวลาสักครู่ นั่นหมายความว่าคุณต้องreadได้รับอนุญาตจากไฟล์และเวลาการเข้าถึงล่าสุดของไฟล์อาจได้รับการอัพเดต

นั่นเป็นมาตรฐานและพกพาอย่างไรก็ตามโปรดทราบว่าwcการใช้งานบางอย่างอาจรวมถึงช่องว่างชั้นนำในผลลัพธ์นั้น วิธีหนึ่งในการกำจัดพวกเขาคือการใช้:

size=$(($(wc -c < "$file")))

หรือเพื่อหลีกเลี่ยงข้อผิดพลาดเกี่ยวกับนิพจน์ทางคณิตศาสตร์ที่ว่างเปล่าในdashหรือyashเมื่อwcไม่สร้างเอาต์พุต (เช่นเมื่อไฟล์ไม่สามารถเปิดได้):

size=$(($(wc -c < "$file") +0))

ksh93มีwcbuiltin (หากคุณเปิดใช้งานคุณยังสามารถเรียกใช้เป็นcommand /opt/ast/bin/wc) ซึ่งทำให้ประสิทธิภาพสูงสุดสำหรับไฟล์ปกติในเชลล์นั้น

ระบบต่าง ๆ มีคำสั่งที่เรียกstatว่าเป็นส่วนต่อประสานกับการโทรstat()หรือlstat()ระบบ

ข้อมูลรายงานเหล่านั้นพบในไอโหนด หนึ่งในข้อมูลนั้นคือst_sizeแอตทริบิวต์ สำหรับไฟล์ปกตินั่นคือขนาดของเนื้อหา (จำนวนข้อมูลที่สามารถอ่านได้ในกรณีที่ไม่มีข้อผิดพลาด (นั่นคือสิ่งที่แอพพลิเคชั่นส่วนใหญ่wc -cใช้ในการปรับให้เหมาะสม) สำหรับ symlink นั่นคือขนาดเป็นไบต์ของพา ธ เป้าหมาย สำหรับไพพ์ที่มีชื่อขึ้นอยู่กับระบบมันเป็น 0 หรือจำนวนไบต์ในบัฟเฟอร์ไพพ์ เช่นเดียวกับอุปกรณ์บล็อกที่ขึ้นอยู่กับระบบคุณจะได้รับ 0 หรือขนาดเป็นไบต์ของที่เก็บข้อมูลพื้นฐาน

คุณไม่จำเป็นต้องได้รับอนุญาตให้อ่านไฟล์เพื่อรับข้อมูลนั้นเพียงค้นหาสิทธิ์ในไดเรกทอรีที่ลิงก์ไปเท่านั้น

ตามลำดับมี:

  • IRIXstat (90's):

    stat -qLs -- "$file"

    ส่งคืนst_sizeแอตทริบิวต์ของ$file( lstat()) หรือ:

    stat -s -- "$file"

    เดียวกันยกเว้นเมื่อ$fileเป็น symlink ซึ่งในกรณีนี้มันเป็นst_sizeไฟล์หลังจากการแก้ปัญหา symlink

  • zsh statbuiltin (ตอนนี้เรียกอีกอย่างว่าzstat) ในzsh/statโมดูล (โหลดด้วยzmodload zsh/stat) (1997):

    stat -L +size -- $file # st_size of file
    stat +size -- $file    # after symlink resolution
    

    หรือเก็บไว้ในตัวแปร:

    stat -L -A size +size -- $file

    เห็นได้ชัดว่ามันมีประสิทธิภาพมากที่สุดในเชลล์นั้น

  • GNUstat (2001); ยังอยู่ใน BusyBox statตั้งแต่ปี 2005 (คัดลอกมาจาก GNU stat):

    stat -c %s -- "$file"  # st_size of file
    stat -Lc %s -- "$file" # after symlink resolution
    

    (ทราบความหมายของ-Lถูกกลับรายการเมื่อเทียบกับ IRIX zsh statหรือ

  • BSDsstat (2002):

    stat -f %z -- "$file"  # st_size of file
    stat -Lf %z -- "$file" # after symlink resolution
    

หรือคุณสามารถใช้stat()/ lstat()ฟังก์ชันของภาษาสคริปต์บางอย่างเช่นperl:

perl -le 'print((lstat shift)[7])' -- "$file"

AIX ยังมีistatคำสั่งที่จะดัมพ์ข้อมูลstat()(ไม่ใช่lstat()ดังนั้นจะไม่ทำงานบน symlink) และคุณสามารถโพสต์กระบวนการด้วยตัวอย่างเช่น:

LC_ALL=C istat "$file" | awk 'NR == 4 {print $5}'

(ขอบคุณ @JeffSchaller สำหรับความช่วยเหลือในการหารายละเอียด )

ในtcsh:

@ size = -Z $file:q

(ขนาดหลังจากความละเอียด symlink)

นานก่อนที่ GNU จะเปิดตัวstatคำสั่งมันสามารถทำได้โดยใช้findคำสั่งGNU พร้อม-printfคำอธิบาย (ในปี 1991 แล้ว):

find -- "$file" -prune -printf '%s\n'    # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution

แม้ว่าปัญหาหนึ่งคือว่าจะไม่ทำงานหาก$fileเริ่มต้นด้วย-หรือเป็นเพรดิเคตfind(เช่น!, (... )

คำสั่งมาตรฐานที่จะได้รับstat()/ ข้อมูลlstat()ls

POSIXly คุณสามารถทำ:

LC_ALL=C ls -dn -- "$file" | awk '{print $5; exit}'

และเพิ่ม-Lให้เหมือนกันหลังจากความละเอียด symlink แต่นั่นไม่ได้ทำงานให้กับแฟ้มอุปกรณ์แม้ว่าที่ 5 สนามเป็นจำนวนที่สำคัญอุปกรณ์แทนของขนาด

สำหรับอุปกรณ์บล็อกระบบที่stat()ส่งคืนค่า 0 st_sizeมักจะมี API อื่นเพื่อรายงานขนาดของอุปกรณ์บล็อก ตัวอย่างเช่น Linux มีBLKGETSIZE64 ioctl()และดิสทริบิวชันส่วนใหญ่มาพร้อมกับblockdevคำสั่งที่สามารถใช้ประโยชน์ได้แล้ว:

blockdev --getsize64 -- "$device_file"

อย่างไรก็ตามคุณต้องได้รับอนุญาตในการอ่านไฟล์อุปกรณ์สำหรับสิ่งนั้น เป็นไปได้ที่จะหาขนาดด้วยวิธีอื่น ตัวอย่างเช่น (ยังอยู่บน Linux):

lsblk -bdno size -- "$device_file"

ควรทำงานยกเว้นอุปกรณ์ที่ว่างเปล่า

วิธีการที่เหมาะกับทุกseekableไฟล์ (เพื่อให้รวมถึงไฟล์ปกติอุปกรณ์ป้องกันและอุปกรณ์ส่วนใหญ่ตัวละครบางคน) คือการเปิดไฟล์และหาทางที่จะสิ้นสุด:

  • ด้วยzsh(หลังจากโหลดzsh/systemโมดูล):

    {sysseek -w end 0 && size=$((systell(0)))} < $file
  • ด้วยksh93:

    < "$file" <#((size=EOF))

    หรือ

    { size=$(<#((EOF))); } < "$file"
  • ด้วยperl:

    perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN' < "$file"

สำหรับท่อชื่อเราได้เห็นว่าบางระบบ (AIX, Solaris, HP / UX อย่างน้อย) ทำให้ปริมาณของข้อมูลในบัฟเฟอร์ท่อที่มีอยู่ใน'sstat() st_sizeบางคน (เช่น Linux หรือ FreeBSD) ทำไม่ได้

อย่างน้อยใน Linux คุณสามารถใช้FIONREAD ioctl()หลังจากเปิดไพพ์ (ในโหมดอ่าน + เขียนเพื่อหลีกเลี่ยงการแฮงค์):

fuser -s -- "$fifo_file" && 
  perl -le 'require "sys/ioctl.ph";
            ioctl(STDIN, &FIONREAD, $n) or die$!;
            print unpack "L", $n' <> "$fifo_file"

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

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

แอตทริบิวต์ inode อีกกลับโดยเป็นstat() st_blocksนั่นคือจำนวนบล็อก 512 ไบต์ที่ใช้เพื่อเก็บข้อมูลของไฟล์ (และบางครั้งข้อมูลเมตาของมันบางอย่างเช่นแอตทริบิวต์เพิ่มเติมบนระบบไฟล์ ext4 บน Linux) ไม่รวม inode เองหรือรายการในไดเรกทอรีที่ไฟล์เชื่อมโยง

ขนาดและการใช้งานดิสก์ไม่จำเป็นต้องเกี่ยวข้องอย่างแน่นหนาเช่นการบีบอัดความกระจัดกระจาย (บางครั้งเมทาดาทา) โครงสร้างพื้นฐานพิเศษเช่นบล็อกทางอ้อมในระบบไฟล์บางระบบมีอิทธิพลในระยะหลัง

โดยทั่วไปจะduใช้ในการรายงานการใช้ดิสก์ คำสั่งส่วนใหญ่ที่แสดงด้านบนจะสามารถรับข้อมูลนั้นได้

  • POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}'
  • POSIXLY_CORRECT=1 du -s -- "$file" (ไม่ใช่สำหรับไดเรกทอรีที่จะรวมการใช้งานดิสก์ของไฟล์ภายใน)
  • GNU find -- "$file" -printf '%b\n'
  • zstat -L +block -- $file
  • GNU stat -c %b -- "$file"
  • BSD stat -f %b -- "$file"
  • perl -le 'print((lstat shift)[12])' -- "$file"

ชัดเจนคำตอบที่ครอบคลุมและให้ข้อมูลมากที่สุด ขอขอบคุณ. ฉันสามารถใช้เพื่อสร้างสคริปต์ข้ามแพลตฟอร์มทุบตีใช้ BSD และ GNU สถิติข้อมูล
oligofren

1
ความจริงแล้วสนุกมาก: GNU coreutils wc -cใช้fstatแล้วอ่านค่าสูงสุดถึงst_blksizeไบต์สุดท้าย เห็นได้ชัดว่าเป็นเพราะไฟล์ในลินุกซ์/procและ/sysยกตัวอย่างเช่นมีขนาดสถิติว่าเป็นเพียงตัวอย่าง เป็นการดีสำหรับความถูกต้อง แต่ไม่ดีถ้าจุดสิ้นสุดของไฟล์อยู่บนดิสก์และไม่อยู่ในหน่วยความจำ (โดยเฉพาะถ้าใช้กับไฟล์จำนวนมากในลูป) และแย่มากหากไฟล์ถูกย้ายไปยังพื้นที่จัดเก็บเทปใกล้ไลน์หรือเช่นระบบไฟล์โปร่งใสการคลายการบีบอัดของ FUSE
Peter Cordes

เค้าก็จะไม่ทำงานเหมือนกันls -go file | awk '{print $3}'
Steven Penny

@StevenPenny ที่-goเป็น SysV พวกเขาจะไม่ทำงานกับ BSD (เป็นทางเลือก (XSI) ใน POSIX) คุณต้องการด้วยls -god file | awk '{print $3; exit}'( -dเพื่อให้สามารถทำงานกับไดเรกทอรีexitสำหรับ symlink ด้วยการขึ้นบรรทัดใหม่ในเป้าหมาย) ปัญหาเกี่ยวกับไฟล์อุปกรณ์ยังคงอยู่
Stéphane Chazelas

1
@ αғsнιη Unix API ไม่แยกความแตกต่างระหว่างไฟล์ข้อความและไบนารี มันคือลำดับทั้งหมดของไบต์ แอปพลิเคชั่นบางตัวอาจต้องการตีความไบต์เหล่านั้นเป็นข้อความ แต่ไม่ชัดเจนว่าwc -cจะรายงานจำนวนไบต์
Stéphane Chazelas

22

สคริปต์นี้รวมหลายวิธีในการคำนวณขนาดไฟล์:

(
  du --apparent-size --block-size=1 "$file" 2>/dev/null ||
  gdu --apparent-size --block-size=1 "$file" 2>/dev/null ||
  find "$file" -printf "%s" 2>/dev/null ||
  gfind "$file" -printf "%s" 2>/dev/null ||
  stat --printf="%s" "$file" 2>/dev/null ||
  stat -f%z "$file" 2>/dev/null ||
  wc -c <"$file" 2>/dev/null
) | awk '{print $1}'

สคริปต์ทำงานบนระบบ Unix จำนวนมากรวมถึง Linux, BSD, OSX, Solaris, SunOS และอื่น ๆ

ขนาดไฟล์แสดงจำนวนไบต์ มันเป็นขนาดที่ชัดเจนซึ่งเป็นไบต์ไฟล์ที่ใช้บนดิสก์ทั่วไปโดยไม่มีการบีบอัดพิเศษหรือพื้นที่เบาบางพิเศษหรือบล็อกที่ไม่ได้ปันส่วน ฯลฯ

สคริปต์นี้มีเวอร์ชันการผลิตพร้อมความช่วยเหลือเพิ่มเติมและตัวเลือกเพิ่มเติมที่นี่: https://github.com/SixArm/file-size


9

สถิติดูเหมือนว่าจะทำสิ่งนี้ด้วยการเรียกระบบน้อยที่สุด:

$ set debian-live-8.2.0-amd64-xfce-desktop.iso

$ strace stat --format %s $1 | wc
    282    2795   27364

$ strace wc --bytes $1 | wc
    307    3063   29091

$ strace du --bytes $1 | wc
    437    4376   41955

$ strace find $1 -printf %s | wc
    604    6061   64793

8

ls -l filename จะให้ข้อมูลมากมายเกี่ยวกับไฟล์รวมถึงขนาดไฟล์สิทธิ์และเจ้าของไฟล์

ขนาดไฟล์ในคอลัมน์ที่ห้าและแสดงเป็นไบต์ ในตัวอย่างด้านล่างขนาดไฟล์อยู่ภายใต้ 2KB:

-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php

แก้ไข:เห็นได้ชัดว่าไม่น่าเชื่อถือเท่าstatคำสั่ง


ฉันคิดว่าทั้งสองls -lและstatคำสั่งให้ข้อมูลขนาดที่เชื่อถือได้ ฉันไม่พบการอ้างอิงใด ๆ ที่ตรงกันข้าม ls -sจะให้ขนาดในจำนวนบล็อก
dabest1

2
@ dabest1 ไม่น่าเชื่อถือในแง่ที่ว่าในยูนิกซ์อื่นเอาต์พุตของพวกเขาอาจแตกต่างกัน (และในบางยูนิกซ์ก็คือ)
Eugene Bujak

ใช่ IIRC, Solaris ไม่แสดงชื่อกลุ่มโดยค่าเริ่มต้นนำไปสู่คอลัมน์ที่น้อยลงในผลลัพธ์
Edward Falk

เนื่องจากขนาดเป็นตัวเลขบริสุทธิ์ล้อมรอบด้วยช่องว่างและปีวันที่เป็นตัวเลขบริสุทธิ์ในรูปแบบที่กำหนดจึงเป็นไปได้ที่จะใช้ regexp ในการจัดการผู้ใช้ + เจ้าของเป็นหนึ่งฟิลด์ไม่ว่าจะมีกลุ่มอยู่หรือไม่ก็ตาม (แบบฝึกหัดสำหรับผู้อ่าน!)
MikeW

5

du filename จะบอกให้คุณใช้งานดิสก์เป็นไบต์

ฉันชอบdu -h filenameซึ่งจะทำให้คุณมีขนาดในรูปแบบที่มนุษย์อ่านได้


2
นั่นหรือstat -c "%s";)

1
รสชาติของduขนาดนี้พิมพ์ออกมาเป็นบล็อก 1024 ไบต์ไม่ใช่จำนวนไบต์ที่เรียบง่าย
ปีเตอร์ลียง

โปรดทราบว่ามาตรฐานduให้เอาต์พุตในหน่วย 512- ไบต์ GNU duใช้ kibibytes แทนเว้นแต่จะเรียกด้วยPOSIXLY_CORRECTในสภาพแวดล้อมของมัน
Stéphane Chazelas

1
สำหรับไฟล์ประเภทไดเรกทอรีที่ให้การใช้งานดิสก์ของไดเรกทอรี แต่ยังรวมถึงไฟล์อื่น ๆ ทั้งหมดภายใน (เรียกซ้ำ)
Stéphane Chazelas

3

สร้างฟังก์ชั่นยูทิลิตี้ขนาดเล็กในเชลล์สคริปต์ของคุณที่คุณสามารถมอบหมายให้

ตัวอย่าง

#! /bin/sh -
# vim: set ft=sh

# size utility that works on GNU and BSD systems
size(){
    case $(uname) in
        (Darwin | *BSD*)
            stat -Lf %z -- "$1";;
        (*) stat -c %s -- "$1"
    esac
}

for f do
    printf '%s\n' "$f : $(gzip < "$f" | wc -c) bytes (versus $(size "$f") bytes)"
done

จากข้อมูลจากคำตอบของ @ Stéphane Chazelas


ดูเพิ่มเติมgzip -v < file > /dev/nullเพื่อตรวจสอบความสามารถในการบีบอัดไฟล์
Stéphane Chazelas

@ StéphaneChazelasไม่แน่ใจว่าฉันคิดว่ามันเป็นการปรับปรุง คำสั่งกรณีเหล่านั้นสามารถนำ noobs ออกได้อย่างง่ายดาย ฉันไม่เคยจำได้ว่าจะทำให้ถูกต้อง :-) เป็นกรณีงบแบบพกพามากขึ้นตั้งแต่ที่คุณทำ? ฉันเห็นประเด็นเมื่อมีมากกว่าสองกรณี แต่อย่างอื่น ... +
oligofren

1
ฉันคิดว่ามันเป็นเรื่องของรสนิยมด้วย แต่ที่นี่เป็นกรณีทั่วไปที่คุณต้องการใช้caseคำสั่ง caseเป็นโครงสร้าง Bourne / POSIX เพื่อทำการจับคู่รูปแบบ [[...]]คือ ksh / bash / zsh เท่านั้น (พร้อมชุดรูปแบบ)
Stéphane Chazelas

2

ฉันพบสายการบิน AWK 1 และมีข้อบกพร่อง แต่ฉันแก้ไข ฉันยังเพิ่มใน PetaBytes หลังจาก TeraBytes

FILE_SIZE=234234 # FILESIZE IN BYTES
FILE_SIZE=$(echo "${FILE_SIZE}" | awk '{ split( "B KB MB GB TB PB" , v ); s=1; while( $1>1024 ){ $1/=1024; s++ } printf "%.2f %s", $1, v[s] }')

เมื่อพิจารณาจากสถิติไม่ได้อยู่ในทุกระบบคุณสามารถใช้โซลูชั่น AWK ได้เกือบทุกครั้ง ตัวอย่าง; ราสเบอร์รี่ Pi ไม่ได้มีสถิติแต่มันก็ไม่ได้มีawk


1
ไม่ใช่สิ่งที่ OP ขอทั้งหมด แต่เป็นงานชิ้นเล็ก ๆ
Spellweaver ยิปซี

0

อีกวิธีหนึ่งที่สอดคล้องกับ POSIX คือการใช้awkกับlength()ฟังก์ชันที่ส่งคืนความยาวเป็นอักขระในแต่ละบรรทัดของไฟล์อินพุตโดยไม่รวมอักขระบรรทัดใหม่ ดังนั้นโดยการทำ

awk '{ sum+=length } END { print sum+NR }' file

เรามั่นใจว่าNRเพิ่มเข้าไปsumดังนั้นจึงส่งผลให้จำนวนตัวอักษรทั้งหมดและจำนวนบรรทัดใหม่ทั้งหมดที่พบในไฟล์ length()ฟังก์ชั่นในการawkใช้เวลาโต้แย้งซึ่งโดยวิธีการเริ่มต้นของlength($0)ซึ่งเป็นสายทั้งในปัจจุบัน


ไม่ใช่ถ้าบรรทัดสุดท้ายไม่ได้ขึ้นบรรทัดใหม่: printf 'a\nb' | awk '{ sum+=length } END { print sum+NR }'ควรพิมพ์ 3 แต่พิมพ์ 4
ไอแซค

-1

ฉันชอบตัวเลือก wc ด้วยตัวเอง จับคู่กับ 'bc' คุณจะได้รับตำแหน่งทศนิยมตามที่คุณต้องการ

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

ฉันขอแนะนำให้แบ่งบรรทัดที่อัฒภาคหากคุณรวมไว้ในสคริปต์

file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"

สคริปต์ของฉันชื่อgpflสำหรับ "รับความยาวไฟล์รูปภาพ" ฉันใช้มันหลังจากทำการmogrifyในไฟล์ใน imagemagick ก่อนที่จะเปิดหรือโหลดรูปภาพใน GUI jpeg viewer อีกครั้ง

ฉันไม่รู้ว่าอัตรานี้เป็น "คำตอบ" อย่างไรเนื่องจากยืมมาจากสิ่งที่เสนอและพูดคุยกันมากแล้ว ดังนั้นฉันจะทิ้งมันไว้ที่นั่น

BZT


1
ฉันต้องการใช้ "สถิติ" หรือ "ls" โดยทั่วไปแล้วฉันไม่ชอบใช้ "wc" เพื่อรับขนาดไฟล์เพราะมันจะอ่านไฟล์ทั้งหมด หากคุณมีไฟล์จำนวนมากหรือโดยเฉพาะไฟล์ขนาดใหญ่อาจใช้เวลานาน แต่โซลูชันของคุณสร้างสรรค์ ... + 1
Kevin Fegan

2
ฉันเห็นด้วยกับความคิดในการใช้ "สถิติ" มากกว่า "wc" สำหรับขนาดไฟล์อย่างไรก็ตามหากคุณใช้ "wc -c" จะไม่มีการอ่านข้อมูล lseek แทนจะถูกใช้เพื่อหาจำนวนไบต์ในไฟล์ lingrok.org/xref/coreutils/src/wc.c#228
bbaja42

1
@ bbaja42: โปรดทราบว่า GNU Coreutils wcอ่านบล็อกสุดท้ายของไฟล์ในกรณีที่stat.st_sizeเป็นเพียงการประมาณ (เช่น Linux /procและ/sysไฟล์) ฉันเดาว่าพวกเขาตัดสินใจที่จะไม่แสดงความคิดเห็นหลักที่ซับซ้อนมากขึ้นเมื่อพวกเขาเพิ่มตรรกะลงไปสองสามบรรทัด: lingrok.org/xref/coreutils/src/wc.c#246
Peter Cordes

-1

วิธีที่เร็วและง่ายที่สุด (IMO) คือ:

bash_var=$(stat -c %s /path/to/filename)

2
จากนั้นถอนคำตอบที่มีอยู่อย่างน้อยหนึ่งคำที่กล่าวถึงสถิติ ไม่จำเป็นต้องทำซ้ำอีกครั้ง ...
เจฟฟ์ Schaller

1
@JeffSchaller ฉันเพิ่งลบคำตอบของ Stephane ตามคำแนะนำของคุณ ฉันคิดว่ามันซับซ้อนเกินไปสำหรับจุดประสงค์ของฉัน นี่คือเหตุผลที่ฉันโพสต์คำตอบง่ายๆสำหรับจิตวิญญาณที่มีใจเดียวกัน
WinEunuuchs2Unix

1
ขอขอบคุณ; เป็นเพียงแค่อินสแตนซ์ที่หกของคำตอบ "สถิติ" ไม่ได้ทำให้การถาม & ตอบง่ายขึ้น แต่จะทำให้ผู้อ่านใหม่ถามตัวเองว่า "คำตอบนี้แตกต่างจากคำถามอื่นอย่างไร" และนำไปสู่ความสับสนมากขึ้นแทนน้อย
Jeff Schaller

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