Wie überprüfe ich die Größe einer Datei mit Bash?

145

Ich habe ein Skript, das nach der Größe 0 sucht, aber ich dachte, es muss eine einfachere Möglichkeit geben, stattdessen nach Dateigrößen zu suchen. Dh file.txtist normalerweise 100k; So überprüfen Sie, ob ein Skript weniger als 90 KB (einschließlich 0) enthält, und lassen es eine neue Kopie erstellen, da die Datei in diesem Fall beschädigt ist.

Was ich gerade benutze ..

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
user349418
quelle
1
unix.stackexchange.com/questions/16640/…
Ciro Santilli 1 冠状 病 六四 事件 法轮功

Antworten:

250

[ -n file.txt ]Überprüft nicht die Größe, sondern, ob die Zeichenfolge file.txtnicht Null ist, sodass sie immer erfolgreich ist.

Wenn Sie sagen möchten, dass "Größe nicht Null ist", benötigen Sie [ -s file.txt ].

Um die Größe einer Datei zu ermitteln, können Sie wc -cdie Größe (Dateilänge) in Byte ermitteln:

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 diesem Fall klingt es so, als ob Sie das wollen.

Wenn Sie jedoch wissen möchten, wie viel Speicherplatz die Datei verwendet, können Sie du -kdie Größe (verwendeter Speicherplatz) in Kilobyte ermitteln:

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

Wenn Sie mehr Kontrolle über das Ausgabeformat benötigen, können Sie sich auch ansehen stat. Unter Linux würden Sie mit so etwas beginnen stat -c '%s' file.txtund unter BSD / Mac OS X mit so etwas stat -f '%z' file.txt.

Mikel
quelle
5
Warum du -b "$file" | cut -f 1statt stat -c '%s' "$file"? Oder stat --printf="%s" "$file"?
Mivk
1
Nur weil es tragbarer ist. BSD und Linux stat haben unterschiedliche Flags.
Mikel
1
Ich musste es modifizieren ... | cut -d' ' -f1, damit es unter Ubuntu funktioniert.
Mikepote
8
Verwenden Sie wc -c < "$file"(beachten Sie das <). In diesem Fall benötigen Sie das | cut ...Teil nicht (was, wie angegeben, unter OSX nicht funktioniert). Der Mindestwert BLOCKSIZEfür duunter OSX ist 512.
mklement0
3
@PetriSirkkala Verwendet auf meinem Linux-System wc -c <filenameauch fstatund seek? Beachten Sie, dass fstatein fd und kein Pfadname verwendet wird.
Mikel
24

Es überrascht mich, dass niemand erwähnt hat stat, um die Dateigröße zu überprüfen. Einige Methoden sind definitiv besser: Es -sist einfacher als alles andere, herauszufinden, ob die Datei leer ist oder nicht, wenn das alles ist, was Sie wollen. Und wenn Sie Dateien mit einer Größe suchen möchten , findist dies mit Sicherheit der richtige Weg.

Ich mag es auch dusehr, die Dateigröße in KB zu erhalten, aber für Bytes würde ich Folgendes verwenden stat:

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

size=$(stat -c%s $filename) # GNU stat?
Daniel C. Sobral
quelle
2
statist eine großartige Idee, aber unter CentOS hat dies für mich funktioniert:size=$(stat -c%s $filename)
Oz Solomon
2
Der Unterschied zwischen GNU und BSD macht diese Alternative leider etwas weniger attraktiv. :(
Lapo
1
stat kann irreführend sein, wenn die Datei spärlich ist. Sie können die von stat gemeldeten Blöcke verwenden, um den verwendeten Speicherplatz zu berechnen.
Ajith Antony
@ AjithAntony Das ist ein interessanter Punkt, der mir nicht in den Sinn gekommen ist. Ich kann sehen stat, dass es in einigen Situationen das Richtige ist, und spärliche Dateien sind in den meisten Situationen nicht relevant, wenn auch sicherlich nicht in allen.
Daniel C. Sobral
17

alternative lösung mit awk und doppelter klammer:

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

if ((SIZE<90000)) ; then 
    echo "less"; 
else 
    echo "not less"; 
fi
fstab
quelle
1
Schön, funktioniert aber nicht unter OSX, wo dues nicht unterstützt wird -b. (Es kann eine bewusste Stil Wahl, aber nur die Alternative zu erwähnen: Sie weglassen können $Präfix innerhalb (( ... ))wenn Variablen Referenzierung: ((SIZE<90000)))
mklement0
1
Eigentlich war es eine Bearbeitung von einem früheren Benutzer, der dachte, es sei falsch, die$
fstab
2
@fstab, können Sie awkmit read( bashinternen Befehl) read SIZE _ <<<$(du -sb "$FILENAME")
ommit
13

Wenn Sie findmit dieser Syntax umgehen, können Sie sie verwenden:

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

Dies wird file.txtnur dann an stdout ausgegeben , wenn die Größe von file.txtweniger als 90 KB beträgt. So führen Sie ein Skript aus, scriptwenn file.txtes eine Größe von weniger als 90 KB hat:

find -maxdepth 1 -name "file.txt" -size -90k -exec script \;
gniourf_gniourf
quelle
3
+1, aber damit es auch unter OSX funktioniert, benötigen Sie ein explizites Zielverzeichnisargument, z. B.:find . -maxdepth 1 -name "file.txt" -size -90k
mklement0
8

Wenn Sie nur die Größe einer Datei suchen:

$ cat $file | wc -c
> 203233
BananaNeil
quelle
1
Dies ist vielleicht die kürzeste praktikable Antwort, aber wahrscheinlich auch die langsamste. :)
SunSparc
2
Ja, aber sicherlich wirtschaftlich überlegen: Kosten für Engineering-Zeit> Kosten für Rechenzeit
BananaNeil
8
wc -c "$file"wurde als Antwort im Jahr 2011 (vor drei Jahren) gegeben. Ja, es wc -c "$file"besteht das Problem, dass sowohl der Dateiname als auch die Anzahl der Zeichen ausgegeben werden. In den ersten Antworten wurde daher ein Befehl zum Trennen der Anzahl hinzugefügt. Aber wc -c < "$file"was dieses Problem behebt, wurde im Mai 2014 als Kommentar hinzugefügt. Ihre Antwort entspricht dieser, außer dass sie eine „nutzlose Verwendung von cat hinzufügt . Außerdem sollten Sie alle Shell-Variablenreferenzen zitieren, es sei denn, Sie haben einen guten Grund, dies nicht zu tun.
G-Man sagt "Reinstate Monica"
1
Sie können dies effizienter gestalten, indem Sie head -c anstelle von cat.if [$ (head -c 90000 $ file | wc -c) -lt 90000] verwenden. dann echo "Datei ist kleiner als 90k"; fi. Unter CentOS getestet, funktioniert es möglicherweise unter BSD oder OSX.
Kevin Keane
@BananaNeil Wie mache ich diesen Vorgang alle 20 Sekunden, damit ich die Inkrementierung der Dateigröße usw. überprüfen kann?
Eine Sahra
6

Dies funktioniert sowohl unter Linux als auch unter 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
}
Neil McGill
quelle
5

stat scheint dies mit den wenigsten Systemaufrufen zu tun:

$ 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

quelle
Wenn ich es richtig verstehe, sollte der Test auch mit Pipe-Umleitung durchgeführt werden?: strace du --bytes $1 2>&1 >/dev/null | wc Wenn dies der Fall ist, habe ich auf der amd64-Architektur unter ArchLinux (normalerweise die neuesten Versionen von allem) 45 Zeilen für du, 46 Zeilen für stat, 47 Zeilen für wcund 72 Zeilen für find.
VasiliNovikov
5
python -c 'import os; print (os.path.getsize("... filename ..."))'

Portable, alle Arten von Python, vermeidet Variationen in statischen Dialekten

user6336835
quelle
4

Um die Dateigröße sowohl unter Linux als auch unter Mac OS X (und vermutlich auch unter anderen BSDs) zu ermitteln, gibt es nicht viele Optionen, und die meisten der hier vorgeschlagenen funktionieren nur auf einem System.

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

Was funktioniert sowohl in Linux als auch in Macs Bash:

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

oder

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

Die anderen Antworten funktionieren gut unter Linux, aber nicht unter Mac:

  • duhat -bauf dem Mac keine Option und der Trick BLOCKSIZE = 1 funktioniert nicht ("Mindestblockgröße 512", was zu einem falschen Ergebnis führt)

  • cut -d' ' -f1 funktioniert nicht, da auf dem Mac die Nummer möglicherweise rechtsbündig und mit Leerzeichen vorne aufgefüllt ist.

Wenn Sie also etwas Flexibles benötigen, ist es entweder perlder -sOperator oder eine wc -cWeiterleitung awk '{print $1}'(awk ignoriert den führenden Leerraum).

Verwenden Sie für den Rest Ihrer ursprünglichen Frage natürlich den Operator -lt(oder -gt):

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

mivk
quelle
3
+1; Wenn Sie wissen, dass Sie die Größe nur in einem arithmetischen Kontext verwenden (in dem führende Leerzeichen ignoriert werden), können Sie dies vereinfachen size=$(wc -c < "$f")(beachten Sie <, dass wcnur eine Zahl gemeldet wird). Zum Vergleich: Vergessen Sie nicht das "Bash-Ful" if (( size < your_wanted_size )); then ...(und auch [[ $size -lt $your_wanted_size ]]).
mklement0
3

Basierend auf der Antwort von gniourf_gniourf,

find "file.txt" -size -90k

schreibt file.txtgenau dann in stdout, wenn die Größe von file.txtweniger als 90 KB beträgt, und

find "file.txt" -size -90k -exec Befehl \;

führt den Befehl aus, commandwenn file.txtdie Größe kleiner als 90 KB ist. Ich habe dies unter Linux getestet. Von find(1),

… Die folgenden Befehlszeilenargumente ( -Hund -Lund -POptionen) sind Namen von zu untersuchenden Dateien oder Verzeichnissen, bis zum ersten Argument, das mit '-' beginnt,…

(Betonung hinzugefügt).

G-Man sagt "Reinstate Monica"
quelle
1
ls -l $file | awk '{print $6}'

Angenommen, der Befehl ls meldet die Dateigröße in Spalte 6

yeugeniuss
quelle
1

Ich würde du's --thresholddafür verwenden. Ich bin nicht sicher, ob diese Option in allen Versionen von verfügbar ist du, sie ist jedoch in der GNU-Version implementiert.

Zitat aus dem Handbuch von du (1) :

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

Hier ist meine Lösung du --threshold=für den Anwendungsfall von 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

Der Vorteil davon ist , dass duein Argument zu dieser Option in einem bekannten Format akzeptieren kann - entweder menschlich wie in 10K, 10MiBoder was auch immer Sie sich wohl fühlen mit - Sie müssen nicht zwischen verschiedenen Formaten / Einheiten seit manuell konvertieren müssen , dudass Griffe.

Als Referenz finden Sie hier die Erklärung zu diesem SIZEArgument auf der Manpage:

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.
Doron Behar
quelle
+1 Ausgezeichnete Option. Leider stecken einige von uns mit älteren Versionen fest du, die dies nicht unterstützen. Die --thresholdOption wurde in Coreutils 8.21 hinzugefügt, das 2013 veröffentlicht wurde .
Amit Naidu
1

Okay, wenn Sie auf einem Mac sind, machen Sie Folgendes: stat -f %z "/Users/Example/config.log" Das war's!

GarfExiXD
quelle