Bagaimana saya bisa mendapatkan ukuran file dalam skrip bash?
Bagaimana cara menetapkan ini ke variabel bash sehingga saya bisa menggunakannya nanti?
pv
dan cat
untuk perintah salin yang menunjukkan progres dan ETA :)
Bagaimana saya bisa mendapatkan ukuran file dalam skrip bash?
Bagaimana cara menetapkan ini ke variabel bash sehingga saya bisa menggunakannya nanti?
pv
dan cat
untuk perintah salin yang menunjukkan progres dan ETA :)
Jawaban:
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 terminal stat in pada Mac OS X.
stat
adalah cara yang paling mudah, dengan asumsi Anda menggunakan Linux atau Cygwin ( stat
bukan standar). wc -c
seperti yang disarankan oleh Eugéne portabel.
stat: illegal option -- c
stat --printf="%s" file.txt
tidak menampilkan apa pun di Debian Jessie ...
stat -f%z myfile.tar
man stat
mengatakan bahwa - printf menghilangkan baris baru yang tertinggal. Gunakan --format
atau -c
untuk melihat hasilnya. Mendapatkan wawasan yang lebih dengan membandingkan stat --printf="%s" file.any | xxd -
kestat -c "%s" file.any | xxd -
file_size_kb=`du -k "$filename" | cut -f1`
Masalah dengan penggunaan stat
adalah bahwa itu adalah ekstensi GNU (Linux). du -k
dan cut -f1
ditentukan oleh POSIX dan karenanya portabel untuk sistem Unix apa pun.
Solaris, misalnya, kapal dengan pesta tapi tidak dengan stat
. Jadi ini tidak sepenuhnya hipotetis.
ls
memiliki masalah yang sama dalam format output yang tepat tidak ditentukan, sehingga penguraian output 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.
du
tidak memberikan ukuran file, itu memberikan indikasi berapa banyak ruang file menggunakan, yang agak berbeda (biasanya ukuran yang dilaporkan oleh du
adalah ukuran file dibulatkan ke jumlah blok terdekat, di mana sebuah blok biasanya 512B atau 1kB atau 4kB).
--bytes
atau -b
alih-alih -k
, harus menjadi jawaban yang diterima.
-h
("manusia") daridu
akan menghasilkan jawaban yang paling tepat untuk kasus umum:, file_size=`du -h "$filename" | cut -f1
karena akan menampilkan K (kilobyte), M (Megabytes) atau G (Gigabytes) yang sesuai.
Anda juga dapat menggunakan perintah "jumlah kata" ( wc
):
wc -c "$filename" | awk '{print $1}'
Masalahnya 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")"
wc -c <"$FILENAME"
memberikan ukuran tanpa cruft lainnya, dengan demikian size=$(wc -c <"$FILENAME")
.
wc -c < file
tampaknya sangat cepat, setidaknya pada OS X. Saya menduga bahwa wc memiliki otak untuk mencoba membuat stat file jika hanya -c yang ditentukan.
wc -c
menggunakan fstat
, tetapi kemudian mencari blok kedua-terakhir dari file dan membaca st_blksize
byte terakhir yang up-to . Rupanya ini karena file di Linux /proc
dan /sys
misalnya memiliki ukuran stat yang hanya perkiraan , dan wc
ingin melaporkan ukuran sebenarnya, bukan ukuran yang dilaporkan stat. Saya kira itu akan aneh untuk wc -c
melaporkan ukuran yang berbeda dari wc
, tetapi itu bukan ide untuk membaca data dari file jika itu adalah file disk yang normal, dan itu tidak ada dalam memori. Atau lebih buruk, penyimpanan tape dekat-line ...
printf
masih melihat lekukan, misalnya printf "Size: $size"
-> size: <4 spaces> 54339
. Di sisi lain echo
mengabaikan spasi. Adakah cara untuk membuatnya konsisten?
fstat
. Coba jalankan strace wc -c </etc/passwd
dan Anda dapat melihat apa yang dilakukannya.
BSD (Mac OS X) stat
memiliki flag argumen format yang berbeda, dan penentu lapangan yang berbeda. Dari man stat(1)
:
-f format
: Menampilkan informasi menggunakan format yang ditentukan. Lihat bagian FORMAT untuk deskripsi format yang valid.z
: Ukuran file dalam byte.Jadi semuanya sekarang:
stat -f%z myfile1.txt
Tergantung apa yang Anda maksud dengan ukuran .
size=$(wc -c < "$file")
akan memberi Anda jumlah byte yang dapat dibaca dari file. TKI, itu ukuran isi file. Namun ia akan membaca isi file (kecuali jika file tersebut adalah file biasa atau symlink ke file biasa di sebagian besar wc
implementasi sebagai optimasi). 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 read
izin untuk file tersebut, dan cap waktu akses terakhir dari file tersebut dapat diperbarui.
Itu standar dan portabel, namun perlu dicatat bahwa beberapa wc
implementasi mungkin termasuk memimpin kosong 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
saat wc
tidak menghasilkan keluaran (seperti saat 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 membuatnya paling efisien untuk file biasa di shell itu.
Berbagai sistem memiliki perintah yang disebut stat
antarmuka untuk panggilan sistem stat()
atau lstat()
.
Informasi laporan tersebut ditemukan dalam inode. Salah satu informasi itu adalah st_size
atribut. Untuk file biasa, itu ukuran konten (seberapa banyak data dapat dibaca dari itu tanpa adanya kesalahan (itulah yang sebagian besar wc -c
implementasi digunakan 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:
IRIXstat
(90-an):
stat -qLs -- "$file"
mengembalikan st_size
atribut $file
( lstat()
) atau:
stat -s -- "$file"
sama kecuali kapan $file
symlink dalam hal ini adalah st_size
file setelah resolusi symlink.
zsh
stat
builtin (sekarang juga dikenal sebagai zstat
) dalam zsh/stat
modul (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.
GNUstat
(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
terbalik dibandingkan dengan IRIX atau zsh
stat
.
BSDstat
(2002):
stat -f %z -- "$file" # st_size of file
stat -Lf %z -- "$file" # after symlink resolution
Atau Anda dapat menggunakan stat()
/ lstat()
fungsi beberapa bahasa scripting seperti perl
:
perl -le 'print((lstat shift)[7])' -- "$file"
AIX juga memiliki istat
perintah yang akan membuang semua informasi stat()
(tidak lstat()
, jadi tidak akan bekerja pada symlinks) dan yang dapat Anda posting setelahnya, misalnya:
LC_ALL=C istat "$file" | awk 'NR == 4 {print $5}'
(terima kasih @JeffSchaller untuk bantuan mencari tahu detailnya ).
Di tcsh
:
@ size = -Z $file:q
(ukuran setelah resolusi symlink)
Jauh sebelum GNU memperkenalkan stat
perintahnya, hal yang sama dapat dicapai dengan find
perintah GNU dengan -printf
predikatnya (sudah pada 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 find
predikat (seperti !
, (
...).
Perintah standar untuk mendapatkan stat()
/ lstat()
informasi 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 bidang ke- 5 adalah nomor utama perangkat, bukan ukurannya.
Untuk perangkat blok, sistem tempat stat()
pengembalian 0 untuk st_size
, biasanya memiliki API lain untuk melaporkan ukuran perangkat blok. Sebagai contoh, Linux memiliki BLKGETSIZE64
ioctl()
, dan sebagian besar distribusi Linux sekarang dikirimkan dengan blockdev
perintah 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.
Pendekatan yang berfungsi untuk semua file yang dapat dicari (termasuk file biasa, sebagian besar perangkat blok dan beberapa perangkat karakter) adalah membuka file dan mencari sampai akhir:
Dengan zsh
(setelah memuat zsh/system
modul):
{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 (AIX, Solaris, HP / UX setidaknya) membuat jumlah data dalam buffer pipa yang tersedia di stat()
's st_size
. Beberapa (seperti Linux atau FreeBSD) tidak.
Di Linux setidaknya, Anda dapat menggunakan FIONREAD
ioctl()
setelah membuka pipa (dalam mode baca + tulis untuk menghindari 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 sementara itu tidak membaca konten 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 meringankan itu tetapi itu tidak mudah karena fuser
mungkin tidak dapat memeriksa semua proses.
Sekarang, sejauh ini kami hanya mempertimbangkan ukuran data primer 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 terkadang 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
digunakan 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 di mana itu termasuk penggunaan disk dari file-file di dalamnya).find -- "$file" -printf '%b\n'
zstat -L +block -- $file
stat -c %b -- "$file"
stat -f %b -- "$file"
perl -le 'print((lstat shift)[12])' -- "$file"
wc -c
digunakan fstat
, tetapi kemudian membaca st_blksize
byte terakhir yang terakhir . Rupanya ini karena file di Linux /proc
dan /sys
misalnya memiliki ukuran stat yang hanya perkiraan . Ini bagus untuk kebenaran, tetapi buruk jika ujung file ada di disk dan tidak ada di memori (khususnya jika digunakan pada banyak file dalam satu lingkaran). Dan sangat buruk jika file dimigrasi ke penyimpanan tape dekat-line , atau misalnya sistem file FUSE transparan-dekompresi.
ls -go file | awk '{print $3}'
-go
adalah yang SysV, mereka tidak akan bekerja pada BSD (opsional (XSI) di POSIX). Anda juga perlu ls -god file | awk '{print $3; exit}'
( -d
agar dapat bekerja pada direktori, exit
untuk symlink dengan baris baru di target). Masalah dengan file perangkat juga tetap ada.
wc -c
yang melaporkan jumlah byte.
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
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
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
Sunting: Ini tampaknya tidak dapat diandalkan seperti stat
perintah.
ls -l
dan stat
perintah memberikan informasi ukuran yang dapat diandalkan. Saya tidak menemukan referensi yang bertentangan. ls -s
akan memberikan ukuran dalam jumlah blok.
du filename
akan memberi tahu Anda penggunaan disk dalam byte.
Saya lebih suka du -h filename
, yang memberi Anda ukuran dalam format yang dapat dibaca manusia.
du
mencetak ukuran dalam blok 1024 byte, bukan hitungan sederhana byte.
du
memberikan output dalam jumlah unit 512-byte. GNU du
menggunakan kibibytes sebagai gantinya kecuali dipanggil dengan POSIXLY_CORRECT
di lingkungannya.
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.
gzip -v < file > /dev/null
untuk memeriksa kompresibilitas file.
case
pernyataan. case
adalah konstruk Bourne / POSIX untuk melakukan pencocokan pola. [[...]]
hanya ksh / bash / zsh (dengan variasi).
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 memiliki awk .
Satu cara lain yang sesuai dengan POSIX adalah menggunakan awk
dengan length()
fungsinya yang mengembalikan panjang, dalam karakter pada setiap baris dari 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 ditemui dalam file. The length()
fungsi dalam awk
mengambil sebuah argumen yang dengan cara standar length($0)
yang untuk seluruh baris saat ini.
printf 'a\nb' | awk '{ sum+=length } END { print sum+NR }'
harus mencetak 3 tetapi mencetak 4.
Saya suka opsi wc sendiri. Dipasangkan dengan 'bc,' Anda bisa mendapatkan desimal ke tempat sebanyak yang Anda mau.
Saya sedang mencari cara untuk memperbaiki skrip yang telah saya buat di kolom 'ukuran file' dari perintah 'ls -alh'. Saya tidak ingin hanya ukuran file integer, dan dua desimal sepertinya cocok, jadi setelah membaca diskusi ini, saya datang dengan kode di bawah ini.
Saya sarankan melanggar garis di titik koma jika Anda memasukkan ini dalam naskah.
file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"
Script saya disebut gpfl , untuk "dapatkan panjang file gambar." Saya menggunakannya setelah melakukan mogrify pada file di imagemagick, sebelum membuka atau memuat ulang gambar di GUI jpeg viewer.
Saya tidak tahu bagaimana ini menilai sebagai "jawaban," karena meminjam banyak dari apa yang sudah ditawarkan dan dibahas. Jadi saya akan meninggalkannya di sana.
BZT
wc
tidak membaca blok terakhir dari file, seandainya stat.st_size
hanya perkiraan (seperti untuk Linux /proc
dan /sys
file). Saya kira mereka memutuskan untuk tidak membuat komentar utama lebih rumit ketika mereka menambahkan logika itu beberapa baris ke bawah: lingrok.org/xref/coreutils/src/wc.c# 246
Metode tercepat dan paling sederhana (IMO) adalah:
bash_var=$(stat -c %s /path/to/filename)
du
dan wc
jawaban yang harus memiliki penafian TIDAK PERNAH MELAKUKANNYA dalam kehidupan nyata. Saya hanya menggunakan jawaban saya dalam aplikasi kehidupan nyata malam ini dan berpikir itu layak untuk dibagikan. Saya kira kita semua memiliki pendapat kami mengangkat bahu .