Bir bash betiğinde bir dosyanın boyutunu nasıl alabilirim?
Bunu daha sonra kullanabilmem için bir bash değişkenine nasıl atayabilirim?
pv
ve bununla eşleştirin cat
:)
Bir bash betiğinde bir dosyanın boyutunu nasıl alabilirim?
Bunu daha sonra kullanabilmem için bir bash değişkenine nasıl atayabilirim?
pv
ve bununla eşleştirin cat
:)
Yanıtlar:
Bir GNU sisteminde ise en iyi bahis:
stat --printf="%s" file.any
Gönderen adam, stat :
% s toplam boyut, bayt olarak
Bir bash betiğinde:
#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."
NOT: stat'ı Mac OS X'te terminalde nasıl kullanacağınız için @ chbrown'un cevabına bakınız .
stat
, Linux veya Cygwin kullandığınızı varsayarak ( stat
standart değil) en kolay yoldur . Eugéne tarafından önerildiğiwc -c
gibi taşınabilir.
stat: illegal option -- c
stat --printf="%s" file.txt
Debian Jessie ile ilgili hiçbir şey çıkmadı ...
stat -f%z myfile.tar
man stat
diyor ki - printf sondaki yeni satırı atlıyor. Çıkışı görmek için --format
veya -c
düğmesini kullanın . Karşılaştırarak daha fazla fikir stat --printf="%s" file.any | xxd -
edinstat -c "%s" file.any | xxd -
file_size_kb=`du -k "$filename" | cut -f1`
Kullanmanın sorunu stat
, bunun bir GNU (Linux) uzantısı olmasıdır. du -k
ve cut -f1
POSIX tarafından belirtilmiştir ve bu nedenle herhangi bir Unix sistemine taşınabilir.
Örneğin, Solaris bash ile birlikte gelir ancak gemiyle birlikte gönderilmez stat
. Yani bu tamamen varsayımsal değildir.
ls
Çıktının tam formatının belirtilmemesinde de benzer bir problem vardır, bu yüzden çıktısının ayrıştırılması taşınabilir olarak yapılamaz. du -h
aynı zamanda bir GNU uzantısıdır.
Mümkün olan yerlerde taşınabilir yapılara bağlı kalın ve gelecekte birilerinin hayatını kolaylaştıracaksınız. Belki kendi
du
dosyanın boyutunu vermez, dosyanın ne kadar alan kullandığına dair bir gösterge verir, bu incelikle farklıdır (genellikle bildirilen du
boyut, en yakın blok sayısına kadar yuvarlanan dosyanın boyutudır, burada bir blok tipik olarak 512B veya 1kB veya 4kB'dir).
--bytes
ya da -b
bunun yerine -k
, kabul edilen cevap olmalıdır.
-h
(Artık "insan") seçeneğidu
genel durumlar için en uygun cevabı üretecek: file_size=`du -h "$filename" | cut -f1
bu K (kilobayt), M (Megabyte) veya uygun şekilde G (Gigabayt) gösterecektir olarak.
"Word count" command ( wc
) komutunu da kullanabilirsiniz :
wc -c "$filename" | awk '{print $1}'
Sorun wc
, dosya adını eklemesi ve çıktının girintili çıkmasıdır. Örneğin:
$ wc -c somefile.txt
1160 somefile.txt
Yalnızca dosya boyutu sayımı elde etmek için tam bir çevrilmiş dil veya akış editörü zincirlemekten kaçınmak istiyorsanız, dosyadaki girdiyi wc
asla görmeyecek şekilde dosyadan girdiyi yönlendirin :
wc -c < "$filename"
Bu son form, aşağıda Gilles tarafından belirtildiği gibi, bir kabuk değişkeni olarak aradığınız değeri kolayca almak için komut değiştirme ile kullanılabilir .
size="$(wc -c <"$filename")"
wc -c <"$FILENAME"
Böylece, başka hiçbir sıkıntı olmadan boyutu verir size=$(wc -c <"$FILENAME")
.
wc -c < file
çok hızlı gözüküyorum, en azından OS X'de. Sadece -c belirtilmişse wc'nin dosyayı statülemeye çalışacak beyinleri olduğunu tahmin ediyorum.
wc -c
kullanır fstat
, ancak dosyanın ikinci son bloğunu arar ve en son st_blksize
baytları okur . Görünüşe bu Linux kullanıcısının dosyalar çünkü /proc
ve /sys
örneğin sadece yaklaşık değerlerdir istatistik boyutları vardır ve wc
gerçek boyutu değil, istatistik bildirilen boyutu bildirmek istiyor. Sanırım wc -c
farklı bir boyutta rapor vermek garip olurdu wc
, ancak normal bir disk dosyasıysa dosyadan veri okumak ve bellekte yoksa, bu bir fikir değildir. Ya da daha kötüsü, sıradaki kaset deposu ...
printf
Girintiyi hala görüyor gibi görünüyor , örneğin printf "Size: $size"
-> size: <4 spaces> 54339
. Diğer yandan echo
boşlukları görmezden geliyor. Tutarlı kılmanın bir yolu var mı?
fstat
. Koşmayı deneyin strace wc -c </etc/passwd
ve ne yaptığını görebilirsiniz.
BSD'ler (Mac OS X'ler) stat
farklı bir format argüman bayrağına ve farklı alan belirleyicilerine sahiptir. Kimden man stat(1)
:
-f format
: Belirtilen formatı kullanarak bilgileri görüntüleyin. Geçerli formatların bir açıklaması için FORMATLAR bölümüne bakın.z
: Dosyanın bayt olarak boyutu.Şimdi hep birlikte:
stat -f%z myfile1.txt
Derken ne demek istediğine bağlıdır boyutu .
size=$(wc -c < "$file")
Size dosyadan okunabilecek bayt sayısını verecektir. IOW, dosya içeriğinin boyutudur. Bununla birlikte, dosyanın içeriğini okuyacaktır (dosyanın çoğu wc
uygulamada bir optimizasyon olarak normal bir dosya veya düzenli dosyaya bağlanması dışında ). Bunun yan etkileri olabilir. Örneğin, bir adlandırılmış boru ne okundu artık tekrar okunabilir ve benzeri şeyler için /dev/zero
ya /dev/random
sonsuz büyüklüktedir, bir süre alacak. Bu da read
dosyaya izin vermeniz gerektiği anlamına gelir ve dosyanın son erişim zaman damgası güncellenebilir.
Bu standart ve portatiftir, ancak bazı wc
uygulamaların bu çıktıda önde gelen boşlukları içerebileceğini unutmayın . Onlardan kurtulmanın bir yolu kullanmaktır:
size=$(($(wc -c < "$file")))
veya boş bir aritmetik ifadeyle ilgili dash
veya hiç çıktı üretmediği yash
zamanki bir hatayı önlemek için wc
(örneğin, dosya açılamadığında):
size=$(($(wc -c < "$file") +0))
ksh93
olan wc
yerleşik (alabilmesi sağlanır, ayrıca olarak çağırabilir command /opt/ast/bin/wc
o kabukta düzenli dosyalar için en verimli kılan).
Çeşitli sistemler adı verilen bir komutu var stat
bir arayüzü stat()
veya lstat()
sistem çağrıları.
Bu bilgi inode'da bulundu. Bu bilgilerden biri st_size
özelliktir. Düzenli dosyalar için, içeriğin boyutu (hata yokluğunda ondan ne kadar veri okunabileceği ( wc -c
uygulamaların çoğunun optimizasyonunda kullandığı şey )) budur. Sembolik bağlantılarda hedef yolun bayt cinsinden boyutudur. Adlandırılmış borular için, sisteme bağlı olarak, ya 0 ya da şu anda boru arabelleğindeki bayt sayısıdır. Sisteme bağlı olarak, 0 veya temel alınan depolamanın bayt cinsinden boyutunu aldığınız blok cihazlar için aynıdır.
Bu bilgiyi almak için dosyaya okuma iznine ihtiyacınız yoktur, yalnızca bağlı olduğu dizine arama iznini verin.
Kronolojik sıraya göre, var:
IRIXstat
(90'lar):
stat -qLs -- "$file"
( ) veya st_size
özniteliğini döndürür :$file
lstat()
stat -s -- "$file"
Aynı zamanda $file
, ne zaman bir sembolik link ise, bu durumda st_size
sembolik link çözünürlüğünden sonraki dosyanın kendisidir.
zsh
stat
yerleşik (şimdi olarak da bilinir zstat
) zsh/stat
modülde (yüklü zmodload zsh/stat
) (1997):
stat -L +size -- $file # st_size of file
stat +size -- $file # after symlink resolution
veya bir değişkende saklamak için:
stat -L -A size +size -- $file
Açıkçası, bu kabukta en verimli olanı.
GNUstat
(2001); ayrıca stat
2005'ten beri BusyBox'ta ( GNU'dan kopyalanmıştır stat
):
stat -c %s -- "$file" # st_size of file
stat -Lc %s -- "$file" # after symlink resolution
( -L
IRIX veya ile karşılaştırıldığında anlamının tersine dikkat edin zsh
stat
.
BSD'lerstat
(2002):
stat -f %z -- "$file" # st_size of file
stat -Lf %z -- "$file" # after symlink resolution
Veya aşağıdaki gibi bir betik dili stat()
/ lstat()
işlevini kullanabilirsiniz perl
:
perl -le 'print((lstat shift)[7])' -- "$file"
AIX ayrıca tüm (örneğin , sembolik bağlantılar üzerinde çalışmayacak) bilgisini silen ve sonradan işlem yapabileceğiniz bir istat
komut içerir, örneğin:stat()
lstat()
LC_ALL=C istat "$file" | awk 'NR == 4 {print $5}'
(Ayrıntıları bulmak için yardım için @JeffSchaller teşekkürler ).
İçinde tcsh
:
@ size = -Z $file:q
(bağlantı noktasının çözünürlüğünden sonraki boyut)
GNU stat
emrini vermeden çok önce , aynısı onun emri ile GNU find
emri ile başarılabilirdi -printf
(zaten 1991'de):
find -- "$file" -prune -printf '%s\n' # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution
Yine de bir mesele, $file
şununla başladığında -
ya da bir find
yüklem ise işe yaramamasıdır (gibi !
, (
...).
stat()
/ lstat()
Bilgi almak için standart komuttur ls
.
POSIXly şunları yapabilirsiniz:
LC_ALL=C ls -dn -- "$file" | awk '{print $5; exit}'
ve -L
aynı bağlantı sembolik çözünürlükten sonra ekleyin . Bu, 5. dosyalar alanın büyüklüğü yerine cihazın büyük sayısı olduğu halde cihaz dosyaları için işe yaramaz .
Blok cihazlar stat()
için st_size
, 0 döndüren sistemler , genellikle blok cihazın boyutunu bildirmek için başka API'lere sahiptir. Örneğin, Linux BLKGETSIZE64
ioctl()
, ve çoğu Linux dağıtımında artık blockdev
bunu kullanabilecek bir komutla geliyor:
blockdev --getsize64 -- "$device_file"
Ancak bunun için cihaz dosyasına okuma iznine ihtiyacınız var. Boyutu başka yollarla türetmek genellikle mümkündür. Örneğin (hala Linux'ta):
lsblk -bdno size -- "$device_file"
Boş cihazlar dışında çalışmalı.
Aranabilir tüm dosyalar için geçerli olan bir yaklaşım (normal dosyalar, çoğu blok ve bazı karakter aygıtları içerir) dosyayı açıp sonuna kadar aramaktır:
İle zsh
( zsh/system
modülü yükledikten sonra ):
{sysseek -w end 0 && size=$((systell(0)))} < $file
İle ksh93
:
< "$file" <#((size=EOF))
veya
{ size=$(<#((EOF))); } < "$file"
ile perl
:
perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN' < "$file"
Adlandırılmış borular için, bazı sistemlerin (en azından AIX, Solaris, HP / UX) boru tamponundaki veri miktarını stat()
'lerde mevcut kıldığını gördük st_size
. Bazıları (Linux veya FreeBSD gibi) yoktur.
En azından Linux'ta FIONREAD
ioctl()
boruyu açtıktan sonra kullanabilirsiniz (asılı kalmamak için okuma + yazma modunda):
fuser -s -- "$fifo_file" &&
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &FIONREAD, $n) or die$!;
print unpack "L", $n' <> "$fifo_file"
Ancak gelmez ise dikkat okumak borunun içeriği, burada adlandırılmış borunun sadece açılış hala yan etkileri olabilir. Öncelikle fuser
bazı işlemlerin boruyu hafifletmek için zaten açık olduğunu kontrol etmek için kullanıyoruz , ancak fuser
tüm işlemleri kontrol edemeyeceği için kusursuz değildir.
Şimdiye kadar, yalnızca dosyalarla ilişkili birincil verilerin boyutunu düşünüyoruz . Bu, meta verilerin boyutunu ve bu dosyayı depolamak için gereken tüm destek altyapısını dikkate almaz.
Tarafından döndürülen bir başka inode niteliği stat()
olduğunu st_blocks
. Bu, dosyanın verilerini depolamak için kullanılan 512 bayt blok sayısıdır (bazen Linux'ta ext4 dosya sistemindeki genişletilmiş öznitelikler gibi meta verilerinden bazıları). Bu inode kendisini veya dosyanın bağlandığı dizinlerdeki girişleri içermez.
Boyut ve disk kullanımı mutlaka sıkıştırma, seyreklik (bazen bazı meta veriler), bazı dosya sistemlerinde dolaylı bloklar gibi ekstra altyapıların ikincisi üzerinde etkisi olur.
Bu genellikle du
disk kullanımını bildirmek için kullanılan şeydir . Yukarıda listelenen komutların çoğu size bu bilgiyi verebilir.
POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}'
POSIXLY_CORRECT=1 du -s -- "$file"
(bunun içindeki dosyaların disk kullanımını içereceği dizinler için değil).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
kullanıyor fstat
, ancak sonuncu st_blksize
baytları okuyor . Görünüşe göre bunun nedeni Linux'lardaki /proc
ve /sys
örneğin dosyaların yalnızca yaklaşık olan stat boyutlarına sahip olmasıdır . Bu doğruluk için iyidir, ancak dosyanın sonu diskte ise ve bellekte değilse (özellikle bir döngüdeki birçok dosyada kullanılıyorsa) kötüdür. Dosya çok yakın bir bant deposuna veya örneğin bir FUSE şeffaf-dekompresyon dosya sistemine geçirilirse çok kötü .
ls -go file | awk '{print $3}'
-go
bunlar SysV olanlar olacak, BSD'ler (POSIX'de isteğe bağlı (XSI)) üzerinde çalışmayacaklardı. Ayrıca ls -god file | awk '{print $3; exit}'
( -d
dizinlerde çalışması exit
, hedefe yeni satırları olan sembolik bağlantılar için) de ihtiyacınız olacaktı . Cihaz dosyalarındaki sorunlar da devam etmektedir.
wc -c
bayt sayısını bildirmez.
Bu komut dosyası dosya boyutunu hesaplamanın birçok yolunu birleştirir:
(
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}'
Betik Linux, BSD, OSX, Solaris, SunOS vb. Dahil olmak üzere birçok Unix sisteminde çalışır.
Dosya boyutu bayt sayısını gösterir. Özel sıkıştırma veya özel seyrek alanlar veya ayrılmamış bloklar, vb.
Bu betiğin burada daha fazla yardım ve daha fazla seçenek içeren bir üretim sürümü var: https://github.com/SixArm/file-size
stat bunu en az sistem çağrısıyla yapıyor gibi görünüyor:
$ 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
dosya boyutu, izinleri ve sahibi de dahil olmak üzere bir dosya hakkında size birçok bilgi verecektir.
Beşinci sütundaki dosya boyutu ve bayt olarak görüntülenir. Aşağıdaki örnekte, dosya boyutu 2KB'nin altında:
-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php
Düzenleme: Bu görünüşte stat
komut kadar güvenilir değil .
ls -l
ve stat
güvenilir boyut bilgi vermek emrediyorum. Aksine hiçbir referans bulamadım. ls -s
blok sayısında boyut verecektir.
du filename
bayt cinsinden disk kullanımını anlatacağım.
Size du -h filename
, okunabilir bir formatta boyut veren, tercih ediyorum .
du
basit bir bayt sayısı değil, 1024 baytlık bloklar halinde yazdırılır.
du
512 bayt birim sayısı verdiğini unutmayın . GNU du
, ortamında çağrılmadığı sürece kibibitler kullanır POSIXLY_CORRECT
.
Kabuk komut dosyalarınızda yetki verebileceğiniz küçük yardımcı işlevler oluşturun.
Örnek
#! /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'ın cevabındaki bilgiye dayanarak.
gzip -v < file > /dev/null
Bir dosyanın sıkıştırılabilirliğini kontrol etmek için ayrıca bakınız .
case
ifade kullanmak isteyeceğiniz tipik bir durum var . case
Bourne / POSIX yapısı desen eşleştirmesidir. [[...]]
sadece ksh / bash / zsh'dir (varyasyonlarla).
Bir AWK 1 astar buldum ve bir böcek vardı ama tamir ettim. Ayrıca TeraBytes'den sonra PetaBytes'e de ekledim.
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] }')
Düşünüldüğünde , stat her sistemde değil, hemen hemen her zaman AWK çözümü kullanabilirsiniz. Örnek; Ahududu Pi stat yok ama awk var .
Başka bir POSIX uyumlu yol , yeni satır karakterleri hariç olmak üzere girdi dosyasının her satırındaki karakterlerde uzunluğu döndüren işlevi awk
ile birlikte kullanmaktır length()
. Yani yaparak
awk '{ sum+=length } END { print sum+NR }' file
Biz sağlamak NR
eklenir sum
ve böylece karakterler ve dosyadaki karşılaşılan satırsonlarının toplam sayısının toplam sayısı sonuçlanan. length()
İşlev awk
varsayılan vasıtasıyla bir argüman hangi sürer length($0)
geçerli bütün hat içindir.
printf 'a\nb' | awk '{ sum+=length } END { print sum+NR }'
3 ama baskılar 4. yazdırmalısınız
Wc seçeneğini kendim seviyorum. 'Bc' ile eşleştirildiğinde, dilediğiniz sayıda yere ondalık alabilirsiniz.
Bir 'ls -alh' komutunun 'dosya boyutu' sütununu uyandırdığım bir komut dosyasını geliştirmek istiyordum. Tamsayı dosya boyutlarını istemedim ve iki ondalık sayı uygun görünüyordu, bu yüzden bu tartışmayı okuduktan sonra aşağıdaki kodu buldum.
Bunu bir komut dosyasına dahil ederseniz, noktalı virgüllerde çizgiyi kesmenizi öneririm.
file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"
Komut dosyama "resim dosyası uzunluğu almak" için gpfl adı verilir . Bir görüntüyü bir GUI jpeg görüntüleyicide açmadan ya da yeniden yüklemeden önce, imagemagick'deki bir dosyada sıkıntı yaptıktan sonra kullanırım .
Bu oranların nasıl bir "cevap" olarak bilmiyorum, çünkü teklif edilmiş ve tartışılmış olanlardan çok ödünç alıyor. Bu yüzden orada bırakacağım.
BZT
wc
olması durumunda stat.st_size
(Linux /proc
ve /sys
dosyalar için olduğu gibi) dosyanın son satırını okuduğunu unutmayın . Sanırım bu mantığı bir kaç satır daha eklediklerinde ana yorumu daha karmaşık hale getirmemeye karar verdiler: lingrok.org/xref/coreutils/src/wc.c#246
En hızlı ve en basit (IMO) yöntemi şudur:
bash_var=$(stat -c %s /path/to/filename)
du
ve wc
yanıt hakkında şikayet edebilirim . Bu gece cevabımı gerçek bir yaşam uygulamasında kullandım ve paylaşımın faydalı olacağını düşündüm. Sanırım hepimizin omuzlarını silkiyoruz .