Come posso ottenere la dimensione di un file in uno script bash?
Come posso assegnarlo a una variabile bash in modo da poterlo utilizzare in seguito?
pve catper un comando di copia che mostra lo stato di avanzamento e l'ETA :)
Come posso ottenere la dimensione di un file in uno script bash?
Come posso assegnarlo a una variabile bash in modo da poterlo utilizzare in seguito?
pve catper un comando di copia che mostra lo stato di avanzamento e l'ETA :)
Risposte:
La tua scommessa migliore se su un sistema GNU:
stat --printf="%s" file.any
Da man stat :
% s dimensione totale, in byte
In uno script bash:
#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."
NOTA: vedi la risposta di @ chbrown per come utilizzare stat nel terminale su Mac OS X.
statè il modo più semplice, supponendo che tu stia usando Linux o Cygwin ( statnon è standard). wc -ccome suggerito da Eugéne è portatile.
stat: illegal option -- c
stat --printf="%s" file.txtnon produce nulla su Debian Jessie ...
stat -f%z myfile.tar
man statdice che --printf omette la nuova riga finale. Utilizzare --formato -cper vedere l'output. Ottieni maggiori informazioni comparando stat --printf="%s" file.any | xxd -astat -c "%s" file.any | xxd -
file_size_kb=`du -k "$filename" | cut -f1`
Il problema con l'utilizzo statè che si tratta di un'estensione GNU (Linux). du -ke cut -f1sono specificati da POSIX e sono quindi portabili su qualsiasi sistema Unix.
Solaris, ad esempio, viene fornito con bash ma non con stat. Quindi questo non è del tutto ipotetico.
lspresenta un problema simile in quanto non viene specificato il formato esatto dell'output, pertanto l'analisi del suo output non può essere eseguita in modo portabile. du -hè anche un'estensione GNU.
Attenersi ai costrutti portatili, ove possibile, e semplificherete la vita di qualcuno in futuro. Forse il tuo.
dunon fornisce le dimensioni del file, fornisce un'indicazione di quanto spazio utilizza il file, che è leggermente diverso (di solito la dimensione indicata da duè la dimensione del file arrotondata per eccesso al numero più vicino di blocchi, dove un blocco è in genere 512B o 1kB o 4kB).
--byteso -binvece di -k, dovrebbe essere la risposta accettata.
-hopzione ("umana")du produrrà la risposta più appropriata per i casi generali:, file_size=`du -h "$filename" | cut -f1poiché visualizzerà K (kilobyte), M (Megabyte) o G (Gigabyte) come appropriato.
Puoi anche usare il comando "conteggio parole" ( wc):
wc -c "$filename" | awk '{print $1}'
Il problema wcè che aggiungerà il nome file e indenterà l'output. Per esempio:
$ wc -c somefile.txt
1160 somefile.txt
Se desideri evitare il concatenamento di una lingua completamente interpretata o di un editor di stream solo per ottenere un conteggio delle dimensioni del file, reindirizza l'input dal file in modo che wcnon veda mai il nome del file:
wc -c < "$filename"
Quest'ultimo modulo può essere usato con la sostituzione dei comandi per afferrare facilmente il valore che stavi cercando come variabile di shell, come menzionato da Gilles di seguito.
size="$(wc -c <"$filename")"
wc -c <"$FILENAME"dà le dimensioni senza nessun'innesto, quindi size=$(wc -c <"$FILENAME").
wc -c < filesembra essere molto veloce, almeno su OS X. Immagino che wc abbia il cervello per provare a stat il file se viene specificato solo -c.
wc -cutilizza GNU fstat, ma cerca il penultimo blocco del file e legge gli ultimi st_blksizebyte fino a . Apparentemente ciò è dovuto al fatto che i file in Linux /proce, /sysad esempio, hanno dimensioni stat solo approssimative e wcvogliono riportare la dimensione effettiva, non la dimensione riportata dalle statistiche. Immagino che sarebbe strano wc -criportare una dimensione diversa da quella wc, ma non è idea leggere i dati dal file se è un normale file su disco e non è in memoria. O peggio, archiviazione su nastro near-line ...
printfveda ancora il rientro, ad es. printf "Size: $size"-> size: <4 spaces> 54339. D'altra parte echoignora lo spazio bianco. Un modo per renderlo coerente?
fstat. Prova a correre strace wc -c </etc/passwde puoi vedere cosa sta facendo.
BSD (Mac OS X) statha un flag di argomento di formato diverso e diversi identificatori di campo. Da man stat(1):
-f format: Visualizza le informazioni utilizzando il formato specificato. Vedi la sezione FORMATI per una descrizione dei formati validi.z: La dimensione del file in byte.Quindi tutti insieme ora:
stat -f%z myfile1.txt
Dipende da cosa intendi per dimensione .
size=$(wc -c < "$file")
ti darà il numero di byte che possono essere letti dal file. IOW, è la dimensione del contenuto del file. Tuttavia leggerà il contenuto del file (tranne se il file è un file normale o un link simbolico al file normale nella maggior parte delle wcimplementazioni come ottimizzazione). Ciò potrebbe avere effetti collaterali. Ad esempio, per una pipe denominata, ciò che è stato letto non può più essere letto di nuovo e per cose come /dev/zeroo /dev/randomche sono di dimensioni infinite, ci vorrà del tempo. Ciò significa anche che è necessaria l' readautorizzazione per il file e potrebbe essere aggiornato l' ultimo timestamp di accesso al file.
È standard e portatile, tuttavia si noti che alcune wcimplementazioni possono includere spazi vuoti iniziali in tale output. Un modo per sbarazzarsi di loro è usare:
size=$(($(wc -c < "$file")))
o per evitare un errore su un'espressione aritmetica vuota in dasho yashquando wcnon produce alcun output (come quando il file non può essere aperto):
size=$(($(wc -c < "$file") +0))
ksh93ha wcincorporato (purché tu lo abiliti, puoi anche invocarlo come command /opt/ast/bin/wc) che lo rende il più efficiente per i file regolari in quella shell.
Vari sistemi hanno un comando chiamato statche è un'interfaccia per le stat()o lstat()chiamate di sistema.
Quelle riportano le informazioni trovate nell'inode. Una di queste informazioni è l' st_sizeattributo. Per i file regolari, questa è la dimensione del contenuto (quanti dati possono essere letti da esso in assenza di errori (questo è ciò che la maggior parte delle wc -cimplementazioni utilizza nella loro ottimizzazione)). Per i collegamenti simbolici, questa è la dimensione in byte del percorso target. Per le pipe con nome, a seconda del sistema, è 0 o il numero di byte attualmente nel buffer delle pipe. Lo stesso vale per i dispositivi a blocchi in cui, a seconda del sistema, si ottiene 0 o la dimensione in byte della memoria sottostante.
Non è necessario il permesso di lettura del file per ottenere tali informazioni, solo il permesso di ricerca nella directory a cui è collegato.
Per ordine cronologico, c'è:
IRIXstat (anni '90):
stat -qLs -- "$file"
restituisce l' st_sizeattributo di $file( lstat()) o:
stat -s -- "$file"
lo stesso tranne quando $fileè un collegamento simbolico nel qual caso è st_sizeil file dopo la risoluzione del collegamento simbolico.
zsh statbuiltin (ora noto anche come zstat) nel zsh/statmodulo (caricato con zmodload zsh/stat) (1997):
stat -L +size -- $file # st_size of file
stat +size -- $file # after symlink resolution
o per memorizzare in una variabile:
stat -L -A size +size -- $file
ovviamente, questo è il più efficiente in quella shell.
GNUstat (2001); anche in BusyBox statdal 2005 (copiato da GNU stat):
stat -c %s -- "$file" # st_size of file
stat -Lc %s -- "$file" # after symlink resolution
(notare che il significato di -Lè invertito rispetto a IRIX o zsh stat.
BSDstat (2002):
stat -f %z -- "$file" # st_size of file
stat -Lf %z -- "$file" # after symlink resolution
Oppure puoi usare la funzione stat()/ lstat()di alcuni linguaggi di scripting come perl:
perl -le 'print((lstat shift)[7])' -- "$file"
AIX ha anche un istatcomando che scaricherà tutte le informazioni stat()(no lstat(), quindi non funzionerà sui collegamenti simbolici) e con le quali potresti post-processarle, ad esempio:
LC_ALL=C istat "$file" | awk 'NR == 4 {print $5}'
(grazie @JeffSchaller per l' aiuto nella comprensione dei dettagli ).
In tcsh:
@ size = -Z $file:q
(dimensioni dopo la risoluzione del collegamento simbolico)
Molto prima che GNU introducesse il suo statcomando, lo stesso poteva essere ottenuto con il findcomando GNU con il suo -printfpredicato (già nel 1991):
find -- "$file" -prune -printf '%s\n' # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution
Un problema però è che non funziona se $fileinizia con -o è un findpredicato (come !, (...).
Il comando standard per ottenere le informazioni stat()/ lstat()è ls.
POSIXly, puoi fare:
LC_ALL=C ls -dn -- "$file" | awk '{print $5; exit}'
e aggiungere -Lper lo stesso dopo la risoluzione del collegamento simbolico. Ciò non funziona per i file di dispositivo, sebbene il 5 ° campo sia il numero maggiore del dispositivo anziché la dimensione.
Per i dispositivi a blocchi, i sistemi in cui stat()restituisce 0 per st_size, di solito hanno altre API per segnalare la dimensione del dispositivo a blocchi. Ad esempio, Linux ha BLKGETSIZE64 ioctl(), e la maggior parte delle distribuzioni Linux ora viene fornita con un blockdevcomando che può farne uso:
blockdev --getsize64 -- "$device_file"
Tuttavia, è necessario disporre dell'autorizzazione di lettura per il file del dispositivo. Di solito è possibile ricavare la dimensione con altri mezzi. Ad esempio (ancora su Linux):
lsblk -bdno size -- "$device_file"
Dovrebbe funzionare ad eccezione dei dispositivi vuoti.
Un approccio che funziona per tutti i file ricercabili (quindi include file regolari, la maggior parte dei dispositivi a blocchi e alcuni dispositivi a caratteri) è quello di aprire il file e cercare fino alla fine:
Con zsh(dopo aver caricato il zsh/systemmodulo):
{sysseek -w end 0 && size=$((systell(0)))} < $fileCon ksh93:
< "$file" <#((size=EOF))
o
{ size=$(<#((EOF))); } < "$file"con perl:
perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN' < "$file"Per le pipe con nome, abbiamo visto che alcuni sistemi (almeno AIX, Solaris, HP / UX) rendono disponibile la quantità di dati nel buffer delle pipe in stat()'s st_size. Alcuni (come Linux o FreeBSD) no.
Almeno su Linux, puoi usare il FIONREAD ioctl()dopo aver aperto la pipe (in modalità lettura + scrittura per evitare che si blocchi):
fuser -s -- "$fifo_file" &&
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &FIONREAD, $n) or die$!;
print unpack "L", $n' <> "$fifo_file"
Tuttavia, nota che mentre non legge il contenuto della pipa, la semplice apertura della pipa denominata qui può comunque avere effetti collaterali. Stiamo usando fuserper verificare innanzitutto che alcuni processi abbiano già aperto il tubo per alleviarlo, ma questo non è infallibile in quanto fuserpotrebbe non essere in grado di controllare tutti i processi.
Ora, finora abbiamo considerato solo la dimensione dei dati primari associati ai file. Ciò non tiene conto delle dimensioni dei metadati e di tutte le infrastrutture di supporto necessarie per archiviare quel file.
Un altro attributo inode restituito da stat()è st_blocks. Questo è il numero di blocchi da 512 byte utilizzati per archiviare i dati del file (e talvolta alcuni dei suoi metadati come gli attributi estesi su filesystem ext4 su Linux). Ciò non include l'inode stesso o le voci nelle directory a cui è collegato il file.
Le dimensioni e l'utilizzo del disco non sono necessariamente strettamente correlati come compressione, scarsità (a volte alcuni metadati), infrastrutture extra come blocchi indiretti in alcuni filesystem hanno un'influenza su quest'ultimo.
Questo è in genere ciò che viene duutilizzato per segnalare l'utilizzo del disco. La maggior parte dei comandi sopra elencati sarà in grado di ottenere tali informazioni.
POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}'POSIXLY_CORRECT=1 du -s -- "$file" (non per le directory in cui ciò includerebbe l'utilizzo del disco dei file all'interno).find -- "$file" -printf '%b\n'zstat -L +block -- $filestat -c %b -- "$file"stat -f %b -- "$file"perl -le 'print((lstat shift)[12])' -- "$file"wc -cusa fstat, ma poi legge gli ultimi st_blksizebyte fino a . Apparentemente ciò è dovuto al fatto che i file in Linux /proce, /sysad esempio, hanno dimensioni stat solo approssimative . Questo è utile per la correttezza, ma male se la fine del file è su disco e non in memoria (specialmente se usata su molti file in un ciclo). E molto male se il file viene migrato su un archivio su nastro near-line o, ad esempio, un filesystem a decompressione trasparente FUSE.
ls -go file | awk '{print $3}'
-gosarebbero quelli SysV, non funzionerebbero su BSD (opzionale (XSI) in POSIX). Avresti anche bisogno ls -god file | awk '{print $3; exit}'( -daffinché funzioni su directory, exitper collegamenti simbolici con le nuove righe nel target). Restano anche i problemi con i file del dispositivo.
wc -criportano il numero di byte.
Questo script combina molti modi per calcolare la dimensione del 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}'
Lo script funziona su molti sistemi Unix tra cui Linux, BSD, OSX, Solaris, SunOS, ecc.
La dimensione del file mostra il numero di byte. È la dimensione apparente, ovvero i byte che il file utilizza su un disco tipico, senza compressione speciale, aree speciali sparse, blocchi non allocati, ecc.
Questo script ha una versione di produzione con più aiuto e più opzioni qui: https://github.com/SixArm/file-size
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
ls -l filename ti fornirà molte informazioni su un file, incluse le dimensioni del file, le autorizzazioni e il proprietario.
La dimensione del file nella quinta colonna e viene visualizzata in byte. Nell'esempio seguente, la dimensione del file è appena inferiore a 2 KB:
-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php
Modifica: apparentemente non è affidabile come il statcomando.
ls -le il statcomando forniscano informazioni sulle dimensioni affidabili. Non ho trovato alcun riferimento al contrario. ls -sdarà dimensioni in numero di blocchi.
du filename ti dirà l'utilizzo del disco in byte.
Preferisco du -h filename, che ti dà le dimensioni in un formato leggibile dall'uomo.
dustampa stampa la dimensione in blocchi di 1024 byte, non un semplice conteggio di byte.
dufornisce un'uscita in numero di unità da 512 byte. GNU duusa invece i kibibyte a meno che non sia chiamato con POSIXLY_CORRECTnel suo ambiente.
Crea piccole funzioni di utilità negli script della shell a cui puoi delegare.
Esempio
#! /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
Sulla base di informazioni fornite dalla risposta di @ Stéphane Chazelas.
gzip -v < file > /dev/nullper verificare la compressibilità di un file.
casedichiarazione. caseè il costrutto Bourne / POSIX per eseguire la corrispondenza dei modelli. [[...]]è solo ksh / bash / zsh (con variazioni).
Ho trovato un Liner AWK 1 e aveva un bug ma l'ho risolto. Ho anche aggiunto PetaBytes dopo 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] }')
Considerando che stat non è presente su ogni singolo sistema, è quasi sempre possibile utilizzare la soluzione AWK. Esempio; il Raspberry Pi non ha stat ma ha awk .
Un altro modo conforme a POSIX sarebbe utilizzare awkcon la sua length()funzione che restituisce la lunghezza, in caratteri su ciascuna riga del file di input, esclusi i caratteri di nuova riga. Così facendo
awk '{ sum+=length } END { print sum+NR }' file
ci assicuriamo che NRvenga aggiunto sum, risultando quindi nel conteggio totale dei caratteri e nel numero totale di nuove righe incontrate nel file. La length()funzione in awkaccetta un argomento che per impostazione predefinita significa length($0)che è per l'intera riga corrente.
printf 'a\nb' | awk '{ sum+=length } END { print sum+NR }'dovrebbe stampare 3 ma stampare 4.
Mi piace anche l'opzione WC. Abbinato a "bc", puoi ottenere decimali in tutti i posti che desideri.
Stavo cercando di migliorare uno script che avevo strappato fuori dalla colonna 'dimensione file' di un comando 'ls -alh'. Non volevo solo dimensioni di file interi e due decimali sembravano adattarsi, quindi dopo aver letto questa discussione, ho trovato il codice qui sotto.
Suggerisco di spezzare la linea al punto e virgola se includi questo in uno script.
file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"
Il mio script si chiama gpfl , per "ottenere la lunghezza del file di immagine". Lo uso dopo aver fatto un mogrify su un file in imagemagick, prima di aprire o ricaricare un'immagine in un visualizzatore jpeg GUI.
Non so come questa sia una "risposta", poiché prende in prestito molto da ciò che è già stato offerto e discusso. Quindi lo lascerò lì.
BZT
wclegge l'ultimo blocco del file, nel caso stat.st_sizefosse solo un'approssimazione (come per Linux /proce i /sysfile). Immagino che abbiano deciso di non rendere il commento principale più complicato quando hanno aggiunto quella logica un paio di righe: lingrok.org/xref/coreutils/src/wc.c#246
Il metodo più rapido e semplice (IMO) è:
bash_var=$(stat -c %s /path/to/filename)
due delle wcrisposte che dovrebbero avere una dichiarazione di non responsabilità MAI FARE QUESTO nella vita reale. Stasera ho usato la mia risposta in un'applicazione reale e ho pensato che valesse la pena condividerla. Immagino che tutti noi abbiamo le nostre opinioni scrollate di spalle .