Come controllare la dimensione di un file usando Bash?


145

Ho uno script che controlla la dimensione 0, ma ho pensato che ci dovrebbe essere un modo più semplice per verificare la dimensione del file. Vale a dire file.txtè normalmente 100k; come fare uno script controllare se è inferiore a 90k (incluso 0) e farlo fare una nuova copia perché il file è corrotto in questo caso.

Quello che sto attualmente usando ..

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

Risposte:


250

[ -n file.txt ]non controlla le sue dimensioni, controlla che la stringa file.txtabbia una lunghezza diversa da zero, quindi avrà sempre successo.

Se vuoi dire "la dimensione è diversa da zero", è necessario [ -s file.txt ].

Per ottenere la dimensione di un file, è possibile utilizzare wc -cper ottenere la dimensione (lunghezza del file) in byte:

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

In questo caso, sembra che sia quello che vuoi.

Cordiali saluti, se si desidera sapere la quantità di spazio su disco utilizzata dal file, è possibile utilizzare du -kper ottenere la dimensione (spazio su disco utilizzato) in kilobyte:

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

Se hai bisogno di un maggiore controllo sul formato di output, puoi anche guardare stat. Su Linux, inizieresti con qualcosa del genere stat -c '%s' file.txt, e su BSD / Mac OS X, qualcosa del genere stat -f '%z' file.txt.


5
Perché du -b "$file" | cut -f 1invece di stat -c '%s' "$file"? Oppure stat --printf="%s" "$file"?
mivk,

1
Solo perché è più portatile. BSD e Linux stat hanno flag diversi.
Mikel,

1
Ho dovuto modificarlo ... | cut -d' ' -f1per farlo funzionare su Ubuntu.
Mikepote,

8
Utilizzare wc -c < "$file"(notare il <), nel qual caso non è necessaria la | cut ...parte (che, come pubblicata, non funziona su OSX). Il BLOCKSIZEvalore minimo per dusu OSX è 512.
mklement0

3
@PetriSirkkala Sul mio sistema Linux, wc -c <filenameusa anche fstate seek? Nota che fstatprende un fd, non un nome di percorso.
Mikel,

24

Mi sorprende che nessuno abbia menzionato statdi controllare la dimensione del file. Alcuni metodi sono decisamente migliori: usare -sper scoprire se il file è vuoto o meno è più facile di ogni altra cosa se è tutto ciò che vuoi. E se vuoi trovare file di una dimensione, allora findè sicuramente la strada da percorrere.

Mi piace anche dumolto ottenere le dimensioni del file in kb, ma, per byte, userei stat:

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

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

2
statè un'ottima idea, ma su CentOS questo è ciò che ha funzionato per me:size=$(stat -c%s $filename)
Oz Solomon,

2
La differenza tra GNU e BSD è ciò che, sfortunatamente, rende questa alternativa un po 'meno attraente. :(
lapo,

1
stat può essere fuorviante se il file è scarso. È possibile utilizzare i blocchi segnalati da stat per calcolare lo spazio utilizzato.
Ajith Antony,

@AjithAntony Questo è un punto interessante che non mi è venuto in mente. Vedo che statè la cosa giusta in alcune situazioni e i file sparsi non sono rilevanti nella maggior parte delle situazioni, anche se certamente non tutti.
Daniel C. Sobral,

17

soluzione alternativa con awk e doppia parentesi:

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

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

1
Bello, ma non funzionerà su OSX, dove dunon supporta -b. (Può essere una scelta di stile consapevole, ma solo per citare l'alternativa: è possibile omettere la $parte interna del prefisso (( ... ))quando si fa riferimento variabili: ((SIZE<90000)))
mklement0

1
In realtà è stata una modifica di un utente precedente che ha pensato che fosse sbagliato omettere il$
fstab

2
@fstab, puoi ommit awkutilizzando read( bashcomando interno):read SIZE _ <<<$(du -sb "$FILENAME")
Jdamian

13

Se findgestisci questa sintassi, puoi usarla:

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

Questo verrà emesso file.txtsu stdout se e solo se la dimensione di file.txtè inferiore a 90k. Per eseguire uno script scriptse file.txtha dimensioni inferiori a 90k:

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

3
+1, ma per farlo funzionare anche su OSX, è necessario un argomento esplicito della directory di destinazione, ad esempio:find . -maxdepth 1 -name "file.txt" -size -90k
mklement0

8

Se stai cercando solo le dimensioni di un file:

$ cat $file | wc -c
> 203233

1
Questa potrebbe essere la risposta più breve possibile, ma è probabilmente anche la più lenta. :)
SunSparc,

2
Sì, ma sicuramente economicamente superiore: costo del tempo di ingegneria> costo del tempo di calcolo
BananaNeil

8
wc -c "$file"è stata data come risposta nel 2011 (tre anni fa). Sì, wc -c "$file"ha il problema che genera il nome del file e il conteggio dei caratteri, quindi le prime risposte hanno aggiunto un comando per separare il conteggio. Ma wc -c < "$file", che risolve quel problema, è stato aggiunto come commento nel maggio 2014. La tua risposta è equivalente a questo, tranne che aggiunge un "uso inutile di cat" . Inoltre, dovresti citare tutti i riferimenti alle variabili della shell a meno che tu non abbia una buona ragione per non farlo.
G-Man dice "Ripristina Monica" il

1
Puoi renderlo più efficiente usando head -c invece di cat.if [$ (head -c 90000 $ file | wc -c) -lt 90000]; quindi echo "Il file è inferiore a 90k"; fi. Testato su CentOS, quindi potrebbe funzionare o meno su BSD o OSX.
Kevin Keane,

@BananaNeil come eseguire questo processo ogni 20 secondi in modo da poter verificare l'incremento delle dimensioni del file così via?
A Sahra,

6

Funziona sia su Linux che su Macos

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 sembra farlo con il minor numero di chiamate di sistema:

$ 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

Se lo capisco correttamente, il test dovrebbe essere eseguito anche con il reindirizzamento della pipe ?: strace du --bytes $1 2>&1 >/dev/null | wc Se è così, allora sull'architettura amd64 su ArchLinux (di solito le ultime versioni di tutto) ho 45 righe per du, 46 righe per stat, 47 righe per wce 72 linee per find.
VasiliNovikov,

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

portatile, tutti i gusti di Python, evita variazioni nei dialetti stat


4

Per ottenere le dimensioni del file in Linux e Mac OS X (e presumibilmente altri BSD), non ci sono molte opzioni e la maggior parte di quelle suggerite qui funzionerà solo su un sistema.

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

cosa funziona in Linux e Mac Bash:

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

o

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

Le altre risposte funzionano bene su Linux, ma non su Mac:

  • dunon ha -bun'opzione in Mac e il trucco BLOCKSIZE = 1 non funziona ("la dimensione minima dei blocchi è 512", il che porta a un risultato sbagliato)

  • cut -d' ' -f1 non funziona perché su Mac, il numero può essere allineato a destra, riempito con spazi davanti.

Quindi, se avete bisogno di qualcosa flessibile, è sia perl's -soperatore, oppure wc -cconvogliato a awk '{print $1}'(awk ignorerà lo spazio bianco che porta).

E, naturalmente, per quanto riguarda il resto della domanda originale, utilizzare l' operatore -lt(o -gt):

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


3
+1; se sai che userai la dimensione solo in un contesto aritmetico (dove lo spazio bianco iniziale viene ignorato), puoi semplificare size=$(wc -c < "$f")(nota il <, che causa wcsolo la segnalazione di un numero). Ri-confronto: non dimenticare il più "schivo" if (( size < your_wanted_size )); then ...(e anche [[ $size -lt $your_wanted_size ]]).
mklement0

3

Sulla base della risposta di gniourf_gniourf,

find "file.txt" -size -90k

scriverà file.txtsu stdout se e solo se la dimensione di file.txtè inferiore a 90 KB e

trova "file.txt" -size -90k -exec command \;

eseguirà il comando commandse file.txtha dimensioni inferiori a 90 KB. Ho provato questo su Linux. Da find(1),

... gli argomenti della riga di comando seguenti (i -H, -Le le -Popzioni) sono prese ad essere nomi di file o cartelle da esaminare, fino al primo argomento che inizia con '-', ...

(enfasi aggiunta).


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

supponendo che il comando ls riporti la dimensione del file nella colonna # 6


1

Vorrei usare du's --thresholdper questo. Non sono sicuro se questa opzione è disponibile in tutte le versioni di duma è implementata nella versione di GNU.

Citando dal manuale di du (1) :

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

Ecco la mia soluzione, usando du --threshold=per il caso d'uso di OP:

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

Il vantaggio di ciò è che dupuò accettare un argomento con quell'opzione in un formato noto - umano come in 10K, 10MiBo qualunque cosa tu ti senta a tuo agio - non è necessario convertire manualmente tra formati / unità poiché lo dugestisce.

Per riferimento, ecco la spiegazione su questo SIZEargomento dalla pagina man:

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 Opzione eccellente. Purtroppo alcuni di noi sono bloccati con versioni precedenti duche non lo supportano. L' --thresholdopzione è stata aggiunta in coreutils 8.21, rilasciata nel 2013 .
Amit Naidu,

1

Ok, se sei su un Mac, fai questo: stat -f %z "/Users/Example/config.log" Ecco fatto!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.