Come posso ottenere la dimensione di un file in uno script bash?
Come lo assegno a una variabile bash in modo da poterlo utilizzare in seguito?
Commenti
Risposta
La soluzione 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: vedere
@chbrown “s answer su come utilizzare stat nel terminale su Mac OS X.
Commenti
- @ haunted85
stat
è il modo più diretto, supponendo che ‘ stia utilizzando Linux o Cygwin (stat
non è ‘ t standard).wc -c
come suggerito da Eug é ne è portatile. -
stat: illegal option -- c
-
stat --printf="%s" file.txt
non ‘ t visualizza qualsiasi cosa su Debian Jessie … - Su MacOS funziona:
stat -f%z myfile.tar
- @woohoo Il tuo prompt sovrascrive loutput.
man stat
dice che –printf omette la nuova riga finale. Utilizza--format
o-c
per visualizzare loutput. Ottieni maggiori informazioni confrontandostat --printf="%s" file.any | xxd -
constat -c "%s" file.any | xxd -
Risposta
file_size_kb=`du -k "$filename" | cut -f1`
Il problema con lutilizzo di stat
è che si tratta di unestensione GNU (Linux). du -k
e cut -f1
sono 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.
ls
ha un problema simile in quanto il formato esatto delloutput non è specificato, quindi lanalisi del suo output non può essere effettuata in modo portabile . du -h
è anche unestensione GNU.
Attenersi a costrutti portatili ove possibile, e semplificherete la vita di qualcuno in futuro. Forse la vostra.
Commenti
-
du
‘ non fornisce dimensione del file, fornisce unindicazione di quanto spazio utilizza il file, che è leggermente diversa (di solito la dimensione riportata dadu
è la dimensione del file arrotondata alla più vicina numero di blocchi, dove un blocco è tipicamente 512B o 1kB o 4kB). - @Gilles, i file sparsi (cioè quelli con buchi in essi) riportano meno della lunghezza.
- Questa, con
--bytes
o-b
invece di-k
, dovrebbe essere la risposta accettata. - @fralau: LOP vuole ” assegnarlo a una variabile bash in modo che possano usarlo in seguito “, quindi è molto più probabile che vogliano un attuatore al valore numerico, non unapprossimazione leggibile dalluomo. Inoltre,
-h
è unestensione GNU; non è standard - Lutilizzo di du con
--apparent-size
flag restituirà un altro dimensione precisa (come indicato su man:print apparent sizes, rather than disk usage; although the apparent size is usually smaller, it may be larger due to holes in ('sparse') files, internal fragmentation, indirect blocks, and the like
)
Risposta
Puoi anche utilizzare il comando” conteggio parole “(wc
):
wc -c "$filename" | awk "{print $1}"
Il problema con wc
è che “aggiungerà il nome del file e farà rientrare loutput. Ad esempio:
$ wc -c somefile.txt 1160 somefile.txt
Se desideri evitare di concatenare un linguaggio interpretato completo o un editor di flusso solo per ottenere un conteggio delle dimensioni del file, reindirizza linput dal file in modo che wc
non veda mai il nome del file:
wc -c < "$filename"
Questultimo modulo può essere utilizzato con la sostituzione del comando per acquisire facilmente il valore che stavi cercando come variabile di shell, come menzionato da Gilles di seguito.
size="$(wc -c <"$filename")"
Commenti
-
wc -c <"$FILENAME"
fornisce la dimensione senza altri cruft, quindisize=$(wc -c <"$FILENAME")
. - Ancora un punto: lho appena testato e
wc -c < file
sembra essere molto veloce, almeno su OS X. I ‘ Immagino che wc abbia il cervello per provare a stat il file se è specificato solo -c. - @EdwardFalk: GNU
wc -c
usafstat
, ma poi cerca il penultimo blocco del file e legge gli ultimist_blksize
byte. Apparentemente ciò è dovuto al fatto che i file in Linux ‘ s/proc
e/sys
ad esempio ha dimensioni delle statistiche che sono solo approssimative ewc
desidera riportare le dimensioni effettive, non quelle riportate dalle statistiche. Immagino che sarebbe strano perwc -c
segnalare una dimensione diversa dawc
, ma ‘ non ha idea di leggere i dati dal file se ‘ è un normale file su disco e ‘ non è in memoria. O peggio, archiviazione su nastro near-line … - Sembra che
printf
veda ancora il rientro, ad es.printf "Size: $size"
– >size: <4 spaces> 54339
. Daltra parte,echo
ignora gli spazi. Qualche modo per renderlo coerente? - @keithpjolley: chiamando
fstat
. Prova a eseguirestrace wc -c </etc/passwd
e potrai vedere cosa sta facendo.
Rispondi
BSD “s (macOS” s) stat
ha un flag di argomento di formato diverso e diversi specificatori di campo. Da man stat(1)
:
-
-f format
: visualizza le informazioni utilizzando il formato specificato. Consulta la sezione FORMATI per una descrizione dei formati validi. - … la sezione FORMATI …
-
z
: la dimensione di file in byte.
Quindi tutti insieme ora:
stat -f%z myfile1.txt
NOTA: vedere @ b01 “s answer su come utilizzare il comando stat
su sistemi GNU / Linux. 🙂
Commenti
- Tieni presente che questa è una soluzione solo BSD. Non ‘ non funziona con GNU
stat
, sfortunatamente.
Risposta
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 collegamento simbolico a un file normale nella maggior parte delle implementazioni wc
come ottimizzazione). Ciò potrebbe avere effetti collaterali. Ad esempio, per una named pipe, ciò che è stato letto non può più essere letto di nuovo e per cose come /dev/zero
o /dev/random
che sono di dimensione infinita, ci vorrà del tempo. Ciò significa anche che è necessaria l read
autorizzazione per il file e l data e ora dellultimo accesso del file potrebbe essere aggiornato.
Questo è standard e portabile, tuttavia si noti che alcune implementazioni di wc
possono includere spazi iniziali nelloutput. Un modo per eliminarli è utilizzare:
size=$(($(wc -c < "$file")))
o per evitare un errore su unespressione aritmetica vuota in dash
o yash
quando wc
non produce output (come quando il file non può “t essere aperto):
size=$(($(wc -c < "$file") +0))
ksh93
ha wc
integrato (ammesso che lo abiliti, puoi anche richiamarlo 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 stat
che “è uninterfaccia per le chiamate di sistema stat()
o lstat()
.
Quelle informazioni sui rapporti trovate nella inode. Una di queste informazioni è lattributo st_size
. Per i file normali, questa è la dimensione del contenuto (quanti dati potrebbero essere letti da esso in assenza di errore (questo è ciò che la maggior parte delle wc -c
utilizza nella loro ottimizzazione) ). Per i collegamenti simbolici, questa è la dimensione in byte del percorso di destinazione. Per le pipe denominate, 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, ottieni 0 o la dimensione in byte dello spazio di archiviazione sottostante.
Non è necessaria lautorizzazione di lettura per il file per ottenere quelle informazioni, solo lautorizzazione di ricerca per directory a cui è collegato.
In ordine cronologico, sono disponibili:
-
IRIX
stat
(90 “s):stat -qLs -- "$file"
restituisce lattributo
st_size
di$file
(lstat()
) o:stat -s -- "$file"
uguale tranne quando
$file
è un link simbolico, nel qual caso è ilst_size
del file dopo la risoluzione del link simbolico. -
zsh
stat
builtin (ora noto anche comezstat
) nel modulozsh/stat
(caricato conzmodload 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.
-
GNU
stat
(2001); anche in BusyBoxstat
dal 2 005 (copiato da GNUstat
):stat -c %s -- "$file" # st_size of file stat -Lc %s -- "$file" # after symlink resolution
(nota il significato di
-L
è invertito rispetto a IRIX ozsh
stat
. -
BSD
stat
(2002):stat -f %z -- "$file" # st_size of file stat -Lf %z -- "$file" # after symlink resolution
Oppure puoi utilizzare la funzione stat()
/ lstat()
di un linguaggio di scripting come perl
:
perl -le "print((lstat shift)[7])" -- "$file"
AIX ha anche un istat
comando che scaricherà tutti i stat()
(non lstat()
, quindi non funzionerà sui link simbolici ) e con cui potresti post-elaborare, ad esempio:
LC_ALL=C istat "$file" | awk "NR == 4 {print $5}"
(grazie @JeffSchaller per il aiutare a capire i dettagli ).
In tcsh
:
@ size = -Z $file:q
(dimensione dopo la risoluzione del collegamento simbolico)
Molto prima che GNU introducesse il suo comando stat
, lo stesso poteva essere ottenuto con GNU find
comando con il suo -printf
predicato (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 “t funziona se $file
inizia con -
o è un find
predicato (come !
, (
…).
Il comando standard per ottenere stat()
/ lstat()
le informazioni sono ls
.
POSSIBILMENTE, puoi fare:
LC_ALL=C ls -dn -- "$file" | awk "{print $5; exit}"
e aggiungi -L
per lo stesso dopo la risoluzione del collegamento simbolico. Ciò non funziona per i file del dispositivo, anche se il campo 5 th è il numero maggiore del dispositivo invece della dimensione.
Per i dispositivi a blocchi, i sistemi in cui stat()
restituisce 0 per st_size
, di solito ha altre API per segnalare le dimensioni del dispositivo a blocchi. Ad esempio, Linux ha BLKGETSIZE64
ioctl()
e la maggior parte delle distribuzioni Linux ora viene fornita con un comando blockdev
che può utilizzarlo:
blockdev --getsize64 -- "$device_file"
Tuttavia, è necessario il permesso di lettura per il file del dispositivo per farlo. Di solito è possibile ricavare la dimensione con altri mezzi. Ad esempio (sempre su Linux):
lsblk -bdno size -- "$device_file"
Dovrebbe funzionare tranne che per i dispositivi vuoti.
Un approccio che funziona per tutti seekable (quindi include file normali, la maggior parte dei dispositivi a blocchi e alcuni dispositivi a caratteri) serve per aprire il file e cercare fino alla fine:
-
Con
zsh
(dopo aver caricato il modulozsh/system
):{sysseek -w end 0 && size=$((systell(0)))} < $file
-
Con
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 denominate, abbiamo visto che alcuni sistemi (AIX, Solaris, HP / UX almeno) rendono disponibile la quantità di dati nel buffer delle pipe in stat()
” st_size
. Alcuni (come Linux o FreeBSD) non “t”.
Almeno su Linux, puoi usare FIONREAD
ioctl()
dopo aver aperto la pipe (in modalità di 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 “t non legge il contenuto della pipe, la semplice apertura della named pipe qui può ancora avere effetti collaterali. Stiamo utilizzando fuser
per verificare che qualche processo abbia già il pipe aperto per alleviarlo, ma questo “non è infallibile perché fuser
potrebbe non essere in grado di controllare tutti i processi.
Finora abbiamo considerato solo la dimensione dei dati primari associati ai file.Ciò non tiene conto della dimensione dei metadati e di tutta linfrastruttura di supporto necessaria per archiviare quel file.
Un altro attributo inode restituito da stat()
è st_blocks
. Questo è il numero di blocchi da 512 byte utilizzati per memorizzare i dati del file (e talvolta alcuni dei suoi metadati come gli attributi estesi sui filesystem ext4 su Linux). “t includere linode stesso o le voci nelle directory a cui è collegato il file.
Le dimensioni e lutilizzo del disco non sono necessariamente strettamente correlati come compressione, scarsità (a volte alcuni metadati), infrastruttura extra come i blocchi indiretti in alcuni filesystem hanno uninfluenza su questi ultimi.
Questo è tipicamente ciò che du
usa per segnalare lutilizzo del disco. La maggior parte dei comandi sopra elencati sarà in grado di ottenere queste informazioni.
-
POSIXLY_CORRECT=1 ls -sd -- "$file" | awk "{print $1; exit}"
-
POSIXLY_CORRECT=1 du -s -- "$file"
(non per directory dove includerebbe il disco usag e dei file allinterno). - GNU
find -- "$file" -printf "%b\n"
-
zstat -L +block -- $file
- GNU
stat -c %b -- "$file"
- BSD
stat -f %b -- "$file"
-
perl -le "print((lstat shift)[12])" -- "$file"
Commenti
- chiaramente la risposta più completa e informativa. grazie. posso usarlo per creare script bash multipiattaforma utilizzando le informazioni sulle statistiche BSD e GNU
- Curiosità: GNU coreutils
wc -c
usafstat
, ma poi legge gli ultimist_blksize
byte. Apparentemente ciò è dovuto al fatto che i file in Linux ‘ s/proc
e/sys
ad esempio hanno dimensioni delle statistiche che sono solo approssimative . Questo è positivo per correttezza, ma male se la fine del file è su disco e non in memoria (specialmente se usato su molti file in un ciclo). E molto male se il file viene migrato a archiviazione su nastro near-line , o ad es. un filesystem di decompressione trasparente FUSE. - non funzionerebbe anche questo
ls -go file | awk '{print $3}'
- @StevenPenny quelli
-go
sarebbero quelli SysV, non ‘ funzionerebbero su BSD (opzionale (XSI) in POSIX). ‘ devi anchels -god file | awk '{print $3; exit}'
(-d
affinché funzioni nelle directory,exit
per collegamenti simbolici con newline nella destinazione). Rimangono anche i problemi con i file di dispositivo. - @ αғsнιη lAPI Unix non fa distinzione tra file di testo e file binari. ‘ tutte le sequenze di byte. Alcune applicazioni potrebbero voler interpretare quei byte come testo ma ovviamente non
wc -c
che riporta il numero di byte.
Risposta
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 inclusi 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, o speciali aree sparse, o blocchi non allocati, ecc.
Questo script ha una versione di produzione con più aiuto e altre opzioni qui: https://github.com/SixArm/file-size
Risposta
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
La risposta
ls -l filename
ti fornirà molte informazioni su un file, comprese le dimensioni del file, i permessi e il proprietario.
La dimensione del file nella quinta colonna e viene visualizzata in byte. Nellesempio seguente, la dimensione del file è di poco inferiore a 2 KB:
-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php
Modifica: Apparentemente non è affidabile quanto il comando stat
.
Commenti
- Penso che entrambi i comandi
ls -l
estat
forniscano informazioni affidabili sulle dimensioni. Non ho trovato alcun riferimento al contrario.ls -s
fornirà la dimensione in numero di blocchi. - @ dabest1 ‘ non è affidabile in un senso che in un altro unix, il loro output può essere diverso (e in alcuni unix lo è).
- Sì, IIRC, Solaris ‘ t mostrava il nome del gruppo per impostazione predefinita, portando a un minor numero di colonne nelloutput.
- Poiché la dimensione è pura numerica, circondata da spazi bianchi, e la data anno è puramente numerica, in un formato definito, sarebbe possibile utilizzare unespressione regolare per trattare lutente + proprietario come un campo, indipendentemente dal fatto che il gruppo fosse presente o meno. (un esercizio per il lettore!)
Risposta
du filename
ti dirà lutilizzo del disco in byte.
Preferisco du -h filename
, che ti dà la dimensione in un formato leggibile dalluomo.
Commenti
- quello o
stat -c "%s"
😉 - Questo tipo di
du
stampa le dimensioni in blocchi di 1024 byte, non un semplice conteggio di byte. - Nota che lo standard
du
fornisce un output in numero di unità da 512 byte. GNUdu
utilizza invece kibibyte a meno che non venga chiamato conPOSIXLY_CORRECT
nel suo ambiente. - Per file di tipo directory , che fornisce lutilizzo del disco della directory ma anche di tutti gli altri file allinterno (ricorsivamente).
Risposta
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
Basato sulle informazioni della risposta di @ Stéphane Chazelas “.
Commenti
- Vedi anche
gzip -v < file > /dev/null
per controllare la compressibilità di un file. - @St é phaneChazelas non sono sicuro se penso che sia stato un miglioramento. quelle affermazioni case possono facilmente rimandare i niubbi; Certamente non ricordo mai come farle bene 🙂 sono affermazioni case intrinsecamente più portabili dato che tu ho visto il punto quando ci sono più di due casi, ma per il resto … +
- Suppongo che ‘ sia anche una questione di gusti, ma qui è ‘ il tipico caso in cui ‘ desideri utilizzare un
case
istruzione.case
è il costrutto Bourne / POSIX per eseguire la corrispondenza dei modelli.[[...]]
è solo ksh / bash / zsh (con variazioni).
Risposta
ho trovato un rivestimento AWK 1 e aveva un bug ma lho 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 stat non è su ogni singolo sistema, puoi quasi sempre utilizzare la soluzione AWK. Esempio; il Raspberry Pi non ha stat ma ha awk .
Commenti
- Completamente NON quello che ha chiesto lOP, ma un bel lavoro.
Risposta
Anche io mi piace lopzione wc. Accoppiato con “bc”, puoi inserire i decimali in tutte le posizioni che desideri.
Stavo cercando di migliorare uno script che avevo quellimbarazzo “ed out la colonna” dimensione file “di un” ls – alh “comando. Non volevo solo dimensioni di file intere, e due decimali sembravano adattarsi, quindi dopo aver letto questa discussione, mi è venuto in mente il codice seguente.
Suggerisco di interrompere la riga al punto e virgola se lo includi 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 lo script si chiama gpfl , per “ottieni la lunghezza del file immagine”. Lo uso dopo aver eseguito un mogrify su un file in imagemagick, prima di aprire o ricaricare unimmagine in un visualizzatore jpeg della GUI.
Non so come valuti una “risposta”, poiché prende molto in prestito da ciò che è già stato offerto e discusso. Quindi lo lascio lì.
BZT
Commenti
- Preferirei usare ” stat ” o ” ls “. In genere ‘ non mi piace usare ” wc ” per ottenere le dimensioni dei file perché legge fisicamente lintero file. Se hai molti file, o file particolarmente grandi, questo può richiedere molto tempo. Ma la tua soluzione è creativa … + 1.
- Sono daccordo con il concetto di utilizzare ” stat ” su ” wc ” per la dimensione del file, tuttavia se utilizzi ” wc -c “, nessun dato verrà letto; invece lseek verrà utilizzato per calcolare il numero di byte in un file. lingrok.org/xref/coreutils/src/wc.c#228
- @ bbaja42 : nota che GNU Coreutils legge lultimo blocco del file, nel caso in cui
stat.st_size
fosse solo unapprossimazione (come per Linux/proc
e/sys
file). Immagino che abbiano deciso di non rendere il commento principale più complicato quando hanno aggiunto quella logica un paio di righe più in basso: lingrok.org/xref/coreutils/src/wc.c#246
Risposta
Il metodo più veloce e semplice (IMO) è:
bash_var=$(stat -c %s /path/to/filename)
Commenti
- Quindi vota una o più delle risposte esistenti che menzionano stat; non cè bisogno di ripeterlo di nuovo …
- @JeffSchaller Ho appena votato positivamente la risposta di Stephane ‘ sulle tue istruzioni.Penso che sia troppo complicato per i miei scopi. Ecco perché ho pubblicato questa semplice risposta per anime affini.
- Grazie; è ‘ solo che una sesta istanza di ” stat ” answer non ‘ t semplifica questa domanda & A, ma preferirebbe che un nuovo lettore si chiedesse ” in che modo questa risposta è diversa dalle altre? ” e portano a più confusione invece che a meno.
- @JeffSchaller immagino. Ma potrei lamentarmi delle molte risposte
du
ewc
che dovrebbero avere una dichiarazione di non responsabilità NON FARLO MAI in realtà vita. Ho appena usato la mia risposta in unapplicazione di vita reale stasera e ho pensato che valesse la pena condividerla. Immagino che tutti abbiamo le nostre opinioni alza le spalle .
pv
ecat
per un comando di copia che mostra lo stato di avanzamento e lorario di arrivo stimato 🙂-s
, quindi puoi semplicemente verificare se un file ha una lunghezza diversa da zero conif [ -s file ]; then echo "file has nonzero size" ; fi