Come posso ottenere la dimensione di un file in uno script bash?

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

  • stackoverflow.com/questions/5920333/how-to-check-size-of-a-file LOL per la migrazione 🙂
  • Accoppialo con pv e cat per un comando di copia che mostra lo stato di avanzamento e lorario di arrivo stimato 🙂
  • stat -c% s file. nome
  • In caso di problema XY (molto ristretto), questo è chiaro: se tutto ciò che serve è testare il file ha una dimensione diversa da zero, bash ha unespressione condizionale -s, quindi puoi semplicemente verificare se un file ha una lunghezza diversa da zero con if [ -s file ]; then echo "file has nonzero size" ; fi

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 confrontando stat --printf="%s" file.any | xxd - con stat -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 da du è 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, quindi size=$(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 usa fstat, ma poi cerca il penultimo blocco del file e legge gli ultimi st_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 e wc desidera riportare le dimensioni effettive, non quelle riportate dalle statistiche. Immagino che sarebbe strano per wc -c segnalare una dimensione diversa da wc, 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 eseguire strace 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 è il st_size del file dopo la risoluzione del link simbolico.

  • zsh stat builtin (ora noto anche come zstat) nel modulo zsh/stat (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.

  • GNU stat (2001); anche in BusyBox stat dal 2 005 (copiato da GNU stat):

    stat -c %s -- "$file" # st_size of file stat -Lc %s -- "$file" # after symlink resolution 

    (nota il significato di -L è invertito rispetto a IRIX o zsh 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 modulo zsh/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 usa fstat, ma poi legge gli ultimi st_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 anche ls -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 e stat 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. GNU du utilizza invece kibibyte a meno che non venga chiamato con POSIXLY_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 e wc 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 .

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *