it-swarm-id.com

Bagaimana saya bisa mendapatkan ukuran file dalam skrip bash?

Bagaimana saya bisa mendapatkan ukuran file dalam skrip bash?

Bagaimana cara menetapkan ini ke variabel bash sehingga saya bisa menggunakannya nanti?

271
haunted85

Taruhan terbaik Anda jika pada sistem GNU:

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

Dari man stat :

Ukuran total% s, dalam byte

Dalam skrip bash:

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

CATATAN: lihat jawaban @ chbrown untuk cara menggunakan stat di terminal pada Mac OS X.

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

Masalah dengan menggunakan stat adalah ekstensi GNU (Linux). du -k dan cut -f1 ditentukan oleh POSIX dan karenanya portabel untuk sistem Unix apa pun.

Solaris, misalnya, dikirimkan dengan bash tetapi tidak dengan stat. Jadi ini tidak sepenuhnya hipotetis.

ls memiliki masalah yang sama yaitu format output yang tepat tidak ditentukan, sehingga penguraian outputnya tidak dapat dilakukan dengan mudah. du -h juga merupakan ekstensi GNU.

Tetap gunakan konstruksi portabel jika memungkinkan, dan Anda akan membuat hidup seseorang lebih mudah di masa depan. Mungkin milikmu sendiri.

97
Nemo

Anda juga bisa menggunakan perintah "Jumlah kata" (wc):

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

Masalah dengan wc adalah ia akan menambahkan nama file dan membuat indentasi hasilnya. Sebagai contoh:

$ wc -c somefile.txt
    1160 somefile.txt

Jika Anda ingin menghindari chaining bahasa yang ditafsirkan penuh atau editor aliran hanya untuk mendapatkan jumlah ukuran file, cukup arahkan kembali input dari file sehingga wc tidak pernah melihat nama file:

wc -c < "$filename"

Formulir terakhir ini dapat digunakan dengan substitusi perintah untuk dengan mudah mengambil nilai yang Anda cari sebagai variabel Shell, seperti yang disebutkan oleh Gilles di bawah ini.

size="$(wc -c <"$filename")"
79
Eugéne

BSD's (macOS's) stat memiliki flag argumen format yang berbeda, dan specifier bidang yang berbeda. Dari man stat(1):

  • -f format: Menampilkan informasi menggunakan format yang ditentukan. Lihat bagian FORMAT untuk deskripsi format yang valid.
  • ... bagian FORMAT ...
  • z: Ukuran file dalam byte.

Jadi semuanya sekarang:

stat -f%z myfile1.txt

CATATAN: lihat jawaban @ b01 untuk cara menggunakan perintah stat pada sistem GNU/Linux. :)

53
chbrown

Tergantung apa yang Anda maksud dengan size.

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

akan memberi Anda jumlah byte yang dapat dibaca dari file. TKI, itu ukuran isi file. Namun ia akan membaca konten file (kecuali jika file tersebut adalah file biasa atau symlink ke file biasa di sebagian besar wc implementasi sebagai pengoptimalan). Itu mungkin memiliki efek samping. Misalnya, untuk pipa bernama, apa yang telah dibaca tidak dapat lagi dibaca lagi dan untuk hal-hal seperti /dev/zero Atau /dev/random Yang berukuran tak terbatas, itu akan memakan waktu cukup lama. Itu juga berarti Anda memerlukan izin read untuk file tersebut, dan cap waktu akses terakhir dari file tersebut dapat diperbarui.

Itu standar dan portabel, namun perhatikan bahwa beberapa implementasi wc dapat menyertakan blanko utama dalam output itu. Salah satu cara untuk menghilangkannya adalah dengan menggunakan:

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

atau untuk menghindari kesalahan tentang ekspresi aritmatika kosong di dash atau yash ketika wc tidak menghasilkan keluaran (seperti ketika file tidak dapat dibuka):

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

ksh93 Memiliki wc builtin (asalkan Anda mengaktifkannya, Anda juga dapat memanggilnya sebagai command /opt/ast/bin/wc) Yang menjadikannya yang paling efisien untuk file biasa di Shell itu.

Berbagai sistem memiliki perintah yang disebut stat yang merupakan antarmuka ke stat() atau lstat() panggilan sistem.

Informasi laporan tersebut ditemukan dalam inode. Salah satu informasi itu adalah atribut st_size. Untuk file biasa, itulah ukuran kontennya (seberapa banyak data dapat dibaca darinya dengan tidak adanya kesalahan (itulah yang paling banyak digunakan oleh wc -c Implementasi dalam optimasi mereka)). Untuk symlink, itu ukuran dalam byte dari jalur target. Untuk pipa bernama, tergantung pada sistem, itu 0 atau jumlah byte saat ini di buffer pipa. Sama untuk perangkat blok di mana tergantung pada sistem, Anda mendapatkan 0 atau ukuran dalam byte penyimpanan yang mendasarinya.

Anda tidak perlu izin baca ke file untuk mendapatkan informasi itu, hanya izin pencarian ke direktori yang ditautkan.

Dengan urutan kronologis, ada:

  • IRIX stat (90-an):

    stat -qLs -- "$file"
    

    mengembalikan atribut st_size dari $file (lstat()) atau:

    stat -s -- "$file"
    

    sama kecuali ketika $file adalah symlink dalam hal ini st_size dari file setelah resolusi symlink.

  • zshstat builtin (sekarang juga dikenal sebagai zstat) dalam modul zsh/stat (Dimuat dengan zmodload zsh/stat ) (1997):

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

    atau untuk menyimpan dalam variabel:

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

    jelas, itu yang paling efisien di Shell itu.

  • GNU stat (2001); juga di BusyBox stat sejak 2005 (disalin dari GNU stat):

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

    (perhatikan arti -L dibalik dibandingkan dengan IRIX atau zshstat.

  • BSDs stat (2002):

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

Atau Anda dapat menggunakan fungsi stat()/lstat() dari beberapa bahasa skrip seperti Perl:

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

AIX juga memiliki perintah istat yang akan membuang semua stat() (bukan lstat(), jadi tidak akan berfungsi pada symlinks) informasi dan yang dapat Anda kirimi proses, misalnya:

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

(terima kasih @JeffSchaller untuk bantuan mencari tahu detailnya ).

Dalam tcsh:

@ size = -Z $file:q

(ukuran setelah resolusi symlink)

Jauh sebelum GNU memperkenalkan perintah stat, hal yang sama dapat dicapai dengan perintah GNU find dengan perintah -printf Predikat (sudah tahun 1991):

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

Namun satu masalah adalah itu tidak berfungsi jika $file Dimulai dengan - Atau merupakan predikat find (seperti !, (. ..).

Perintah standar untuk mendapatkan informasi stat()/lstat() adalah ls.

POSIXly, Anda dapat melakukan:

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

dan tambahkan -L untuk resolusi symlink yang sama setelah. Itu tidak berfungsi untuk file perangkat meskipun di mana 5th bidang adalah nomor utama perangkat, bukan ukuran.

Untuk perangkat blok, sistem di mana stat() mengembalikan 0 untuk st_size, Biasanya memiliki API lain untuk melaporkan ukuran perangkat blok. Sebagai contoh, Linux memiliki BLKGETSIZE64ioctl(), dan sebagian besar distribusi Linux sekarang dikirimkan dengan perintah blockdev yang dapat memanfaatkannya:

blockdev --getsize64 -- "$device_file"

Namun, Anda perlu izin baca ke file perangkat untuk itu. Biasanya dimungkinkan untuk mendapatkan ukuran dengan cara lain. Misalnya (masih di Linux):

lsblk -bdno size -- "$device_file"

Seharusnya berfungsi kecuali untuk perangkat kosong.

Suatu pendekatan yang bekerja untuk semua dicari file (termasuk file biasa, sebagian besar perangkat blok dan beberapa perangkat karakter) adalah membuka file dan mencari sampai akhir:

  • Dengan zsh (setelah memuat modul zsh/system):

    {sysseek -w end 0 && size=$((systell(0)))} < $file
    
  • Dengan ksh93:

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

    atau

    { size=$(<#((EOF))); } < "$file"
    
  • dengan Perl:

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

Untuk pipa bernama, kita telah melihat bahwa beberapa sistem (setidaknya AIX, Solaris, HP/UX) membuat jumlah data dalam buffer pipa tersedia dalam stat() [st_size]. Beberapa (seperti Linux atau FreeBSD) tidak.

Setidaknya di Linux, Anda dapat menggunakan FIONREADioctl() setelah membuka pipa (dalam mode baca + tulis untuk menghindarinya menggantung):

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

Namun perhatikan bahwa meskipun tidak baca isi pipa, pembukaan pipa yang dinamai di sini masih dapat memiliki efek samping. Kami menggunakan fuser untuk memeriksa terlebih dahulu bahwa beberapa proses sudah memiliki pipa terbuka untuk meringankannya, tetapi itu tidak mudah karena fuser mungkin tidak dapat memeriksa semua proses.

Sekarang, sejauh ini kami hanya mempertimbangkan ukuran primer data yang terkait dengan file. Itu tidak memperhitungkan ukuran metadata dan semua infrastruktur pendukung yang diperlukan untuk menyimpan file itu.

Atribut inode lain yang dikembalikan oleh stat() adalah st_blocks. Itu adalah jumlah blok 512 byte yang digunakan untuk menyimpan data file (dan kadang-kadang beberapa metadata-nya seperti atribut yang diperluas pada sistem file ext4 di Linux). Itu tidak termasuk inode itu sendiri, atau entri dalam direktori file yang ditautkan.

Ukuran dan penggunaan disk tidak selalu terkait erat seperti kompresi, sparseness (kadang-kadang beberapa metadata), infrastruktur tambahan seperti blok tidak langsung di beberapa sistem file memiliki pengaruh pada yang terakhir.

Itulah yang biasanya du gunakan untuk melaporkan penggunaan disk. Sebagian besar perintah yang tercantum di atas akan dapat memberi Anda informasi itu.

  • POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}'
  • POSIXLY_CORRECT=1 du -s -- "$file" (Bukan untuk direktori yang mencakup penggunaan disk dari file-file di dalamnya).
  • 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"
32

Script ini menggabungkan banyak cara untuk menghitung ukuran file:

(
  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}'

Skrip ini berfungsi pada banyak sistem Unix termasuk Linux, BSD, OSX, Solaris, SunOS, dll.

Ukuran file menunjukkan jumlah byte. Ini adalah ukuran yang jelas, yaitu byte yang digunakan file pada disk biasa, tanpa kompresi khusus, atau area jarang khusus, atau blok yang tidak terisi, dll.

Skrip ini memiliki versi produksi dengan bantuan lebih banyak dan lebih banyak opsi di sini: https://github.com/SixArm/file-size

22

stat tampaknya melakukan ini dengan panggilan sistem paling sedikit:

$ 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
9
user150821

ls -l filename akan memberi Anda banyak informasi tentang file, termasuk ukuran file, izin, dan pemiliknya.

Ukuran file di kolom kelima, dan ditampilkan dalam byte. Dalam contoh di bawah ini, ukuran file hanya di bawah 2KB:

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

Edit: Ini tampaknya tidak dapat diandalkan seperti perintah stat.

8
Druckles

du filename akan memberi tahu Anda penggunaan disk dalam byte.

Saya lebih memilih du -h filename, yang memberi Anda ukuran dalam format yang dapat dibaca manusia.

5
Teddy

Saya menemukan liner AWK 1, dan ada bug tetapi saya memperbaikinya. Saya juga menambahkan PetaBytes setelah 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] }')

Mengingat stat tidak ada di setiap sistem, Anda hampir selalu dapat menggunakan solusi AWK. Contoh; Raspberry Pi tidak memiliki stat tetapi memang memiliki awk.

3
findrbot_admin

Buat fungsi utilitas kecil di skrip Shell yang dapat Anda delegasikan.

Contoh

#! /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

Berdasarkan info dari jawaban @ Stéphane Chazelas.

3
oligofren

Satu cara lain yang sesuai dengan POSIX adalah menggunakan awk dengan fungsi length() yang mengembalikan panjang, dalam karakter pada setiap baris file input, tidak termasuk karakter baris baru. Jadi dengan melakukan

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

kami memastikan NR ditambahkan ke sum, sehingga menghasilkan jumlah total karakter dan jumlah baris baru yang ditemukan dalam file. length() function dalam awk mengambil argumen yang secara default berarti length($0) yang untuk seluruh baris saat ini.

0
Inian