Bash kullanarak bir dosyanın boyutu nasıl kontrol edilir?


145

0 boyutu kontrol eden bir komut dosyası var, ancak bunun yerine dosya boyutlarını kontrol etmek için daha kolay bir yol olması gerektiğini düşündüm. Yani file.txtnormalde 100k'dir; bir komut dosyasının 90k'den (0 dahil) az olup olmadığını nasıl kontrol edeceğini ve dosya bu durumda bozuk olduğu için yeni bir kopyasını wget yapmasını nasıl sağlayabilirsiniz.

Şu anda ne kullanıyorum ..

if [ -n file.txt ]
then
 echo "everything is good"
else
 mail -s "file.txt size is zero, please fix. " myemail@gmail.com < /dev/null
 # Grab wget as a fallback 
 wget -c https://www.server.org/file.txt -P /root/tmp --output-document=/root/tmp/file.txt
 mv -f /root/tmp/file.txt /var/www/file.txt
fi

Yanıtlar:


250

[ -n file.txt ]boyutunu kontrol etmez, dizenin file.txtsıfır olmayan uzunluğunu kontrol eder , bu nedenle her zaman başarılı olur.

"Boyut sıfır değil" demek istiyorsanız, ihtiyacınız var [ -s file.txt ].

Bir dosyanın boyutunu wc -calmak için, boyutu (dosya uzunluğu) bayt olarak almak için kullanabilirsiniz :

file=file.txt
minimumsize=90000
actualsize=$(wc -c <"$file")
if [ $actualsize -ge $minimumsize ]; then
    echo size is over $minimumsize bytes
else
    echo size is under $minimumsize bytes
fi

Bu durumda, istediğiniz gibi geliyor.

Ancak FYI, dosyanın ne kadar disk alanı kullandığını bilmek istiyorsanız du -k, kilobayt cinsinden boyutu (kullanılan disk alanı) almak için kullanabilirsiniz :

file=file.txt
minimumsize=90
actualsize=$(du -k "$file" | cut -f 1)
if [ $actualsize -ge $minimumsize ]; then
    echo size is over $minimumsize kilobytes
else
    echo size is under $minimumsize kilobytes
fi

Çıktı formatı üzerinde daha fazla kontrole ihtiyacınız varsa, şunlara da bakabilirsiniz stat. Linux'ta, stat -c '%s' file.txtBSD / Mac OS X gibi bir şeyle başlayacaksınız stat -f '%z' file.txt.


5
Neden du -b "$file" | cut -f 1yerine stat -c '%s' "$file"? Yoksa stat --printf="%s" "$file"?
mivk

1
Sadece daha portatif olduğu için. BSD ve Linux stat farklı bayraklara sahiptir.
Mikel

1
... | cut -d' ' -f1Ubuntu üzerinde çalışmak için değiştirmek zorunda kaldım .
Mikepote

8
Kullanın wc -c < "$file"(not edin <), bu durumda | cut ...parçaya ihtiyacınız yoktur (yayınlandığı gibi OSX'te çalışmaz). OSX BLOCKSIZEiçin minimum değer duşudur 512.
mklement0

3
@PetriSirkkala Linux sistemimde wc -c <filenameayrıca fstatve seek? fstatBir yol adı değil, bir fd alan unutmayın .
Mikel

24

statDosya boyutunu kontrol etmek için hiç kimsenin bahsetmediği beni şaşırtıyor . Bazı yöntemler kesinlikle daha iyidir: -sdosyanın boş olup olmadığını bulmak için kullanmak , istediğiniz her şeyden daha kolaydır. Ve eğer bir büyüklükteki dosyaları bulmak istiyorsanız find, kesinlikle gitmek için bir yoldur.

Ben de dukb dosya boyutunu almak için çok seviyorum , ama, bayt için, ben kullanmak istiyorum stat:

size=$(stat -f%z $filename) # BSD stat

size=$(stat -c%s $filename) # GNU stat?

2
statharika bir fikir, ama CentOS'ta bu benim için işe yaradı:size=$(stat -c%s $filename)
Oz Solomon

2
GNU ve BSD arasındaki fark maalesef bu alternatifi biraz daha az çekici kılan şeydir. :(
lapo

1
stat seyrek ise stat yanıltıcı olabilir. Kullanılan alanı hesaplamak için stat tarafından bildirilen blokları kullanabilirsiniz.
Ajith Antony

@AjithAntony Bu benim başıma gelmeyen ilginç bir nokta. Görebildiğim statolmanın haklı tamamı olmasa, bazı durumlarda bir şey ve seyrek dosyalar çoğu durumda ilgili değildir.
Daniel C. Sobral

17

awk ve çift parantezli alternatif çözüm:

FILENAME=file.txt
SIZE=$(du -sb $FILENAME | awk '{ print $1 }')

if ((SIZE<90000)) ; then 
    echo "less"; 
else 
    echo "not less"; 
fi

1
Güzel, ancak dudesteklenmeyen OSX üzerinde çalışmaz -b. (Bilinçli tarzı seçim olabilir, ama sadece alternatif söz: Eğer atlayabilirsiniz $önek içini (( ... ))değişkenleri başvururken: ((SIZE<90000)))
mklement0

1
Aslında$
fstab

2
@fstab, ( iç komut) awkkullanarak ommit yapabilirsiniz :readbashread SIZE _ <<<$(du -sb "$FILENAME")
Jdamian

13

Senin Eğer findbu sözdizimi kolları, bunu kullanabilirsiniz:

find -maxdepth 1 -name "file.txt" -size -90k

Bu, file.txtyalnızca boyutu file.txt90k'den küçükse stdout'a çıkar . Bir komut dosyası yürütmek için scripteğer file.txtaz 90k daha bir büyüklüğe sahiptir:

find -maxdepth 1 -name "file.txt" -size -90k -exec script \;

3
+1, ancak aynı zamanda OSX'te çalışmasını sağlamak için açık bir hedef dizin bağımsız değişkenine ihtiyacınız vardır, örneğin:find . -maxdepth 1 -name "file.txt" -size -90k
mklement0

8

Yalnızca bir dosyanın boyutunu arıyorsanız:

$ cat $file | wc -c
> 203233

1
Bu, uygulanabilir en kısa cevap olabilir, ancak muhtemelen en yavaş olanıdır. :)
SunSparc

2
Evet, ama kesinlikle ekonomik açıdan üstün: Mühendislik süresinin maliyeti> Hesaplama süresinin maliyeti
BananaNeil

8
wc -c "$file"2011 yılında (üç yıl önce) cevap olarak verilmiştir. Evet, wc -c "$file"dosya adının yanı sıra karakter sayısını da çıkarması sorunu var, bu nedenle ilk yanıtlar sayımı ayırmak için bir komut ekledi. Ama wc -c < "$file", hangi sorun Yanıtınız bu eşdeğerdir Mayıs 2014 yılında bir yorum olarak eklendiğini düzeltmeleri, bir ekler hariç “nin yararsız kullanımı cat . Ayrıca, iyi bir nedeniniz olmadığı sürece tüm kabuk değişken referanslarını alıntılamanız gerekir.
G-Man, 'Monica'yı Yeniden Başlat' diyor

1
Cat.if [$ (head -c 90000 $ file | wc -c) -lt 90000] yerine head -c komutunu kullanarak bunu daha verimli hale getirebilirsiniz. sonra yankı "Dosya 90k'den küçük"; fi. CentOS üzerinde test edilmiştir, bu nedenle BSD veya OSX üzerinde çalışabilir veya çalışmayabilir.
Kevin Keane

@BananaNeil Bu işlemi her 20 saniyede nasıl yapacağım, böylece dosya boyutunun artımını kontrol edebilir miyim?
Bir Sahra

6

Bu hem linux hem de macos'ta çalışır

function filesize
{
    local file=$1
    size=`stat -c%s $file 2>/dev/null` # linux
    if [ $? -eq 0 ]
    then
        echo $size
        return 0
    fi

    eval $(stat -s $file) # macos
    if [ $? -eq 0 ]
    then
        echo $st_size
        return 0
    fi

    return -1
}

5

stat bunu en az sistem çağrısı ile 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

Doğru anlıyorsam, test aynı zamanda boru yeniden yönlendirme ile yapılmalıdır ?: strace du --bytes $1 2>&1 >/dev/null | wc Durum buysa, ArchLinux'daki amd64 mimarisinde (genellikle her şeyin en son sürümleri) 45 satırım du, 46 satırım stat, 47 satırım wcve İçin 72 satır find.
VasiliNovikov

5
python -c 'import os; print (os.path.getsize("... filename ..."))'

taşınabilir, tüm python lezzetleri, stat lehçelerindeki varyasyonları önler


4

Hem Linux hem de Mac OS X'te (ve muhtemelen diğer BSD'lerde) dosya boyutunu elde etmek için çok fazla seçenek yoktur ve burada önerilenlerin çoğu sadece bir sistemde çalışacaktır.

Verilen f=/path/to/your/file,

Linux ve Mac'in Bash'inde ne işe yarıyor :

size=$( perl -e 'print -s shift' "$f" )

veya

size=$( wc -c "$f" | awk '{print $1}' )

Diğer cevaplar Linux'ta iyi çalışıyor, ancak Mac'te çalışmıyor:

  • du-bMac'te bir seçenek yok ve BLOCKSIZE = 1 hile çalışmıyor ("minimum blok boyutu 512'dir", bu da yanlış bir sonuca neden olur)

  • cut -d' ' -f1 Mac'te çalışmaz, çünkü sayı sağa hizalanmış, öndeki boşluklarla doldurulmuş olabilir.

Esnek bir şey gerekiyorsa, o da var perl'nın -soperatör veya wc -ctaşınıyor awk '{print $1}'(awk lider boşluk yok sayacak).

Ve elbette, orijinal sorunuzun geri kalanıyla ilgili olarak -lt(veya -gt) operatörünü kullanın:

if [ $size -lt $your_wanted_size ]; then vb.


3
+ 1; boyutu yalnızca aritmetik bir bağlamda kullanacağınızı biliyorsanız (önde gelen boşluk dikkate alınmazsa) basitleştirebilirsiniz size=$(wc -c < "$f")( yalnızca bir sayının raporlanmasına <neden wcolan). Yeniden karşılaştırma: daha "bash-ful" if (( size < your_wanted_size )); then ...(ve ayrıca [[ $size -lt $your_wanted_size ]]) unutmayın.
mklement0

3

Gniourf_gniourf'un cevabına dayanarak,

find "file.txt" -size -90k

yazacak file.txtstdout'a ancak ve büyüklüğü sadece file.txtaz 90K daha ve

"file.txt" -boyut -90k -exec komutunu bul \;

90K'dan küçük bir boyutu commandvarsa komutu yürütür file.txt. Bunu Linux'ta test ettim. Gönderen find(1),

... Komut satırı argümanları (aşağıdaki -H, -Lve -Pisimleri olarak kabul seçenekleri) olan dosyaları veya ile başlayan ilk argüman kadar incelenecek dizinleri '-', ...

(vurgu eklenmiştir).


1
ls -l $file | awk '{print $6}'

ls komutunun # 6 sütununda dosya boyutunu bildirdiği varsayılarak


1

Ben kullanırım du's --thresholdbunun için. Bu seçeneğin tüm sürümlerinde mevcut olduğundan emin değil, duancak GNU'nun sürümünde uygulandığından emin değilim .

Du (1) el kitabından alıntı :

-t, --threshold=SIZE
       exclude entries smaller than SIZE if positive, or entries greater
       than SIZE if negative

İşte benim du --threshold=OP kullanımı için kullanarak benim çözüm :

THRESHOLD=90k
if [[ -z "$(du --threshold=${THRESHOLD} file.txt)" ]]; then
    mail -s "file.txt size is below ${THRESHOLD}, please fix. " myemail@gmail.com < /dev/null
    mv -f /root/tmp/file.txt /var/www/file.txt
fi

Bunun avantajı, yani duolduğu gibi her iki insan - bilinen bir biçimde o seçeneğe bir argümanı kabul edebilir 10K, 10MiBveya her ne rahat hissediyorum - sen beri biçimler / birimler arasındaki elle dönüştürmek gerekmez dukolları söyledi.

Referans olarak, bu SIZEargümanla ilgili man sayfasından açıklama:

The SIZE argument is an integer and optional unit (example: 10K is 
10*1024). Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers
of 1000). Binary prefixes can be used, too: KiB=K, MiB=M, and so on.

+1 Mükemmel seçenek. Ne yazık ki bazılarımız dubunu desteklemeyen eski sürümlerle sıkışıp kaldık . --thresholdSeçenek, coreutils 8.21 eklendi 2013 yılında piyasaya .
Amit Naidu

1

Tamam, Mac kullanıyorsanız, bunu yapın: stat -f %z "/Users/Example/config.log" Hepsi bu kadar!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.