Hvordan kan jeg få størrelsen på en fil i et bash-script?

Hvordan kan jeg få størrelsen på en fil i et bash-script?

Hvordan tildeler jeg dette til en bash-variabel, så jeg kan bruge den senere?

Kommentarer

  • stackoverflow.com/questions/5920333/how-to-check-size-of-a-file LOL for migreringen 🙂
  • Par dette med pv og cat til en kopikommando, der viser fremskridt og ETA 🙂
  • stat -c% s-fil. navn
  • I tilfælde af (meget snævert) XY-problem er dette pænt: hvis alt hvad du behøver er at teste filen har en nul størrelse, har bash et betinget udtryk -s, så du kan bare teste, om en fil har en nul længde med if [ -s file ]; then echo "file has nonzero size" ; fi

Svar

Din bedste chance, hvis du er på et GNU-system:

stat --printf="%s" file.any 

Fra mandstat :

% s samlede størrelse i byte

I et bash-script:

#!/bin/bash FILENAME=/home/heiko/dummy/packages.txt FILESIZE=$(stat -c%s "$FILENAME") echo "Size of $FILENAME = $FILESIZE bytes." 

BEMÆRK: se

@chbrowns svar til, hvordan man bruger stat i terminal på Mac OS X.

Kommentarer

  • @ haunted85 stat er den mest ligefremme måde, forudsat at du ‘ bruger Linux eller Cygwin (stat isn ‘ t standard). wc -c som foreslået af Eug é ne er bærbar.
  • stat: illegal option -- c
  • stat --printf="%s" file.txt betyder ikke ‘ t output noget på Debian Jessie …
  • På MacOS fungerer dette: stat -f%z myfile.tar
  • @woohoo Din prompt overskriver output. man stat siger, at –printf udelader den efterfølgende nye linje. Brug --format eller -c for at se output. Få mere indsigt ved at sammenligne stat --printf="%s" file.any | xxd - til stat -c "%s" file.any | xxd -

Svar

file_size_kb=`du -k "$filename" | cut -f1` 

Problemet med at bruge stat er, at det er en GNU (Linux) udvidelse. du -k og cut -f1 er specificeret af POSIX og er derfor bærbare til ethvert Unix-system.

Solaris sendes for eksempel med bash men ikke med stat . Så dette er ikke helt hypotetisk.

ls har et lignende problem, idet det nøjagtige format for output ikke er specificeret, så parsing af output kan ikke gøres bærbart . du -h er også en GNU-udvidelse.

Hold dig til bærbare konstruktioner, hvor det er muligt, og du vil gøre det lettere for nogen i fremtiden. Måske din egen.

Kommentarer

  • du giver ikke ‘ t filens størrelse, det giver en indikation af, hvor meget plads filen bruger, hvilket er subtilt forskellig (normalt er størrelsen rapporteret af du størrelsen på filen afrundet op til den nærmeste antal blokke, hvor en blok typisk er 512B eller 1kB eller 4kB).
  • @ Gilles, sparsomme filer (dvs. dem med huller i) rapporterer mindre end længden.
  • Dette med --bytes eller -b i stedet for -k, skal være det accepterede svar.
  • @fralau: OPen vil ” tildele dette til en bash-variabel, så de kan bruge den senere “, så det er meget mere sandsynligt, at de vil have en aktu al numerisk værdi, ikke en menneskelig læsbar tilnærmelse. -h er også en GNU-udvidelse; det er ikke standard
  • Brug af du med --apparent-size flag returnerer en mere præcis størrelse (som angivet på en mand: 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)

Svar

Du kan også bruge kommandoen” ordtælling “(wc):

wc -c "$filename" | awk "{print $1}" 

Problemet med wc er, at det “tilføjer filnavnet og indrykker output. For eksempel:

$ wc -c somefile.txt 1160 somefile.txt 

Hvis du gerne vil undgå at kæde et fuldt fortolket sprog eller en streameditor for kun at få et filstørrelsesantal, skal du bare omdirigere input fra filen, så wc aldrig ser filnavnet:

wc -c < "$filename" 

Denne sidste form kan bruges med kommandosubstitution for let at få fat i den værdi, du søgte som en shellvariabel, som nævnt af Gilles nedenfor.

size="$(wc -c <"$filename")" 

Kommentarer

  • wc -c <"$FILENAME" giver størrelsen uden nogen anden cruft, således size=$(wc -c <"$FILENAME").
  • Bare et punkt mere: Jeg testede det lige og wc -c < file ser ud til at være meget hurtig, i det mindste på OS X. I ‘ Jeg gætter på, at wc har hjernen til at prøve at statificere filen, hvis kun -c er angivet.
  • @EdwardFalk: GNU wc -c bruger fstat, men søger derefter den næstsidste blok af filen og læser den sidste op til st_blksize byte. Tilsyneladende er fordi filer i Linux ‘ s /proc og /sys har for eksempel statstørrelser, der kun er omtrentlige , og wc ønsker at rapportere den faktiske størrelse, ikke den stat-rapporterede størrelse. Jeg antager, at det ville være underligt for wc -c at rapportere en anden størrelse end wc, men det ‘ er ikke idé om at læse data fra filen, hvis den ‘ er en normal diskfil, og den ‘ ikke er i hukommelsen. Eller værre, båndopbevaring nær linjen …
  • Det ser ud til, at printf stadig ser indrykket, f.eks. printf "Size: $size" – > size: <4 spaces> 54339. På den anden side ignorerer echo det hvide område. Nogen måde at gøre det konsistent på?
  • @keithpjolley: Ved at ringe til fstat. Prøv at køre strace wc -c </etc/passwd, og du kan se, hvad den laver.

Svar

BSD “s (macOS” s) stat har et andet formatargumentflag og forskellige feltangivere. Fra man stat(1):

  • -f format: Vis oplysninger i det angivne format. Se afsnittet FORMATER for en beskrivelse af gyldige formater.
  • … afsnittet FORMATER …
  • z: Størrelsen på fil i bytes.

Så alt sammen nu:

stat -f%z myfile1.txt 

BEMÆRK: se @ b01 “s svar til, hvordan man bruger kommandoen stat på GNU / Linux-systemer. 🙂

Kommentarer

  • Bemærk, at dette kun er en BSD-løsning. Det fungerer ikke ‘ med GNU stat desværre.

Svar

Afhænger af hvad du mener med størrelse .

size=$(wc -c < "$file") 

giver dig antallet af byte, der kan læses fra filen. IOW, det er størrelsen på filens indhold. Den læser dog indholdet af filen (undtagen hvis filen er en almindelig fil eller symlink til almindelig fil i de fleste wc implementeringer som en optimering). Det kan have bivirkninger. For eksempel for et navngivet rør kan det, der er blevet læst, ikke længere læses igen og for ting som /dev/zero eller /dev/random som er af uendelig størrelse, det tager et stykke tid. Det betyder også, at du har brug for read tilladelse til filen, og filens sidste tidsstempel for filen kan muligvis opdateres.

Det er standard og bærbart, men vær opmærksom på, at nogle wc -implementeringer kan omfatte førende emner i dette output. En måde at slippe af med dem er at bruge:

size=$(($(wc -c < "$file"))) 

eller at undgå en fejl om et tomt aritmetisk udtryk i dash eller yash når wc ikke producerer noget output (som når filen ikke kan åbnes):

size=$(($(wc -c < "$file") +0)) 

ksh93 har wc indbygget (forudsat at du aktiverer det, kan du også påberåbe det som command /opt/ast/bin/wc), hvilket gør det til det mest effektive til almindelige filer i den shell.

Forskellige systemer har en kommando kaldet stat at “er en grænseflade til stat() eller lstat() systemopkald.

Disse rapportoplysninger findes i inode. En af disse oplysninger er attributten st_size. For almindelige filer, der er størrelsen på indholdet (hvor mange data der kan læses fra det i fravær af fejl (det er, hvad de fleste wc -c implementeringer bruger i deres optimering) ). For symlinks er størrelsen i byte på målstien. For navngivne rør er det enten 0 eller antallet af bytes, der aktuelt er i rørbufferen, afhængigt af systemet. Samme for blokkenheder, hvor du afhængigt af systemet får 0 eller størrelsen i byte på det underliggende lager.

Du behøver ikke læsetilladelse til filen for at få disse oplysninger, kun søgningstilladelse til katalog det er linket til.

Efter kronologisk rækkefølge er der:

  • IRIX stat (90 “s):

    stat -qLs -- "$file" 

    returnerer st_size attribut for $file (lstat()) eller:

    stat -s -- "$file" 

    samme undtagen når $file er et symlink, i hvilket tilfælde det er st_size af filen efter symlinkopløsning.

  • zsh stat indbygget (nu også kendt som zstat) i zsh/stat -modulet (indlæst med zmodload zsh/stat) (1997):

    stat -L +size -- $file # st_size of file stat +size -- $file # after symlink resolution 

    eller at gemme i en variabel:

    stat -L -A size +size -- $file 

    selvfølgelig er det mest effektivt i den skal.

  • GNU stat (2001); også i BusyBox stat siden 2 005 (kopieret fra GNU stat):

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

    (bemærk betydningen af -L er omvendt sammenlignet med IRIX eller zsh stat.

  • BSDer stat (2002):

    stat -f %z -- "$file" # st_size of file stat -Lf %z -- "$file" # after symlink resolution 

Eller du kan bruge stat() / lstat() -funktionen på et eller andet scriptingsprog som perl:

perl -le "print((lstat shift)[7])" -- "$file" 

AIX har også en istat -kommando , som vil dumpe al stat() (ikke lstat(), så du vil ikke arbejde på symlinks ) oplysninger, og som du kan efterbehandle med, for eksempel:

LC_ALL=C istat "$file" | awk "NR == 4 {print $5}" 

(tak @JeffSchaller for hjælp til at finde ud af detaljerne ).

I tcsh:

@ size = -Z $file:q 

(størrelse efter symlinkopløsning)

Længe før GNU introducerede sin stat kommando, kunne det samme opnås med GNU find kommando med dens -printf predikat (allerede i 1991):

find -- "$file" -prune -printf "%s\n" # st_size of file find -L -- "$file" -prune -printf "%s\n" # after symlink resolution 

Et problem er dog, at det ikke arbejde, hvis $file starter med - eller er et find prædikat (som !, ( …).

Standardkommandoen for at få stat() / lstat() oplysninger er ls.

POSIX, du kan gøre:

LC_ALL=C ls -dn -- "$file" | awk "{print $5; exit}" 

og tilføj -L til det samme efter symlinkopløsning. Det fungerer ikke for enhedsfiler, selvom 5 th -feltet er enhedens hovednummer i stedet for størrelsen.

For blokkenheder, systemer hvor stat() returnerer 0 for st_size, har normalt andre APIer til at rapportere størrelsen på blokkenheden. For eksempel har Linux BLKGETSIZE64 ioctl(), og de fleste Linux-distributioner leveres nu med en blockdev kommando, der kan gøre brug af den:

blockdev --getsize64 -- "$device_file" 

Du skal dog læse tilladelse til enhedsfilen til det. Det er normalt muligt at udlede størrelsen på anden måde. For eksempel (stadig på Linux):

lsblk -bdno size -- "$device_file" 

Skal fungere bortset fra tomme enheder.

En tilgang, der fungerer for alle søgbare filer (inkluderer også almindelige filer, de fleste blokeringsenheder og nogle karakterenheder) er at åbne filen og søge til slutningen:

  • Med zsh (efter indlæsning af zsh/system -modulet):

    {sysseek -w end 0 && size=$((systell(0)))} < $file 
  • Med ksh93:

    < "$file" <#((size=EOF)) 

    eller

    { size=$(<#((EOF))); } < "$file" 
  • med perl:

    perl -le "seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN" < "$file" 

For navngivne rør har vi set, at nogle systemer (i det mindste AIX, Solaris, HP / UX) gør mængden af data i rørbufferen tilgængelig i stat() “s st_size. Nogle (som Linux eller FreeBSD) don t.

I det mindste på Linux kan du bruge FIONREAD ioctl() efter at have åbnet røret (i læse + skrivetilstand for at undgå, at det hænger):

fuser -s -- "$fifo_file" && perl -le "require "sys/ioctl.ph"; ioctl(STDIN, &FIONREAD, $n) or die$!; print unpack "L", $n" <> "$fifo_file" 

Bemærk dog, at mens det ikke “t læser indholdet af røret, kan den blotte åbning af det navngivne rør her stadig have bivirkninger. Vi bruger fuser til først at kontrollere, at en eller anden proces allerede har røret åbent for at afhjælpe det, men at det ikke er idiotsikkert, da fuser ikke være i stand til at kontrollere alle processer.

Nu har vi indtil videre kun overvejet størrelsen på de primære data, der er knyttet til filerne.Det tager ikke højde for størrelsen på metadataene og al den understøttende infrastruktur, der er nødvendig for at gemme filen.

En anden inode-attribut, der returneres af stat() er st_blocks. Det er antallet af 512 byteblokke, der bruges til at gemme filens data (og nogle gange nogle af dens metadata som de udvidede attributter på ext4-filsystemer på Linux). Det gør ikke “t inkluderer selve inoden, eller de poster i mapperne, filen er linket til.

Størrelse og diskbrug er ikke nødvendigvis tæt forbundet, da komprimering, tyndhed (nogle gange nogle metadata), ekstra infrastruktur som indirekte blokke i nogle filsystemer har indflydelse på sidstnævnte.

Det er typisk, hvad du bruger til at rapportere diskbrug. De fleste af de ovennævnte kommandoer vil være i stand til at få disse oplysninger.

  • POSIXLY_CORRECT=1 ls -sd -- "$file" | awk "{print $1; exit}"
  • POSIXLY_CORRECT=1 du -s -- "$file" (ikke til mapper hvor det ville inkludere disk usag e af filerne inden for).
  • 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"

Kommentarer

  • klart det mest omfattende og informative svar. tak skal du have. Jeg kan bruge dette til at oprette bash-scripts på tværs af platforme ved hjælp af BSD- og GNU-statistikoplysninger
  • Sjov kendsgerning: GNU coreutils wc -c bruger fstat, men læser derefter de sidste op til st_blksize bytes. Tilsyneladende er fordi filer i Linux ‘ s /proc og /sys har for eksempel statstørrelser, der kun er omtrentlige . Dette er godt for korrekthed, men dårligt, hvis slutningen af filen er på disken og ikke i hukommelsen (især hvis den bruges på mange filer i en loop). Og meget dårligt, hvis filen migreres til nærbåndsopbevaring eller f.eks. et FUSE-filsystem med transparent dekompression.
  • ville ikke dette arbejde også ls -go file | awk '{print $3}'
  • @StevenPenny de -go ville være SysV-dem, de ville ikke ‘ t arbejde på BSDer (valgfri (XSI) i POSIX). Du ‘ d har også brug for ls -god file | awk '{print $3; exit}' (-d for at det kan fungere i mapper, exit til symlinks med nye linjer i målet). Problemer med enhedsfiler forbliver også.
  • @ αғsнιη Unix API skelner ikke mellem tekst og binære filer. Det ‘ er alle sekvenser af bytes. Nogle applikationer vil muligvis fortolke disse bytes som tekst, men tydeligvis ikke wc -c, som rapporterer antallet af byte.

Svar

Dette script kombinerer mange måder at beregne filstørrelsen på:

( 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}" 

Scriptet fungerer på mange Unix-systemer inklusive Linux, BSD, OSX, Solaris, SunOS osv.

Filstørrelsen viser antallet af byte. Det er den tilsyneladende størrelse, som er de bytes, filen bruger på en typisk disk uden speciel komprimering eller specielle sparsomme områder eller ikke-allokerede blokke osv.

Dette script har en produktionsversion med mere hjælp og flere muligheder her: https://github.com/SixArm/file-size

Svar

stat ser ud til at gøre dette med de færreste systemopkald:

$ 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 

Svar

ls -l filename giver dig masser af oplysninger om en fil, herunder dens filstørrelse, tilladelser og ejer.

Filstørrelsen i den femte kolonne og vises i byte. I nedenstående eksempel er filstørrelsen lige under 2 KB:

-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php 

Rediger: Dette er tilsyneladende ikke så pålideligt som kommandoen stat.

Kommentarer

  • Jeg tror, at både ls -l og stat kommando giver pålidelig størrelse information. Jeg fandt ingen henvisning til det modsatte. ls -s giver størrelse i antal blokke.
  • @ dabest1 det ‘ er ikke pålidelig på en måde som i en anden unix, deres output kan være forskellig (og i nogle unix er det).
  • Ja, IIRC, Solaris viste ikke ‘ t som standard gruppens navn, fører til færre kolonner i output.
  • Da størrelsen er ren numerisk, omgivet af hvidt mellemrum, og datoåret er rent numerisk, i et defineret format, ville det være muligt at bruge en regexp til at behandle bruger + ejer som et felt, uanset om gruppen var til stede eller ej. (en øvelse for læseren!)

Svar

du filename fortæller dig diskbrug i bytes.

Jeg foretrækker du -h filename, hvilket giver dig størrelsen i et læsbart format.

Kommentarer

  • det eller stat -c "%s"😉
  • Denne smag af du udskriver størrelse i blokke af 1024 bytes, ikke et simpelt antal bytes.
  • Bemærk, at standard du giver en output i antal 512 byte enheder. GNU du bruger i stedet kibibytes, medmindre det kaldes med POSIXLY_CORRECT i sit miljø.
  • For filer af typen katalog , der giver diskbrugen af biblioteket, men også af alle de andre filer inden for (rekursivt).

Svar

Opret små hjælpefunktioner i dine shell-scripts, som du kan delegere til.

Eksempel

#! /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 

Baseret på info fra @ Stéphane Chazelas “svar.

Kommentarer

  • Se også gzip -v < file > /dev/null for at kontrollere komprimerbarheden af en fil.
  • @St é phaneChazelas er ikke sikker på, om jeg synes, det var en forbedring. disse sager kan let udskyde noobs; Jeg kan bestemt aldrig huske, hvordan man får dem rigtige 🙂 er sagsudsagn i sagens natur mere bærbare, siden du så det? jeg kan se det punkt, når der er mere end to tilfælde, men ellers … +
  • Jeg formoder, at det ‘ også er et spørgsmål om smag, men her er det ‘ det typiske tilfælde, hvor du ‘ d ønsker at bruge en case udsagn. case er Bourne / POSIX-konstruktionen til at lave mønstermatchning. [[...]] er kun ksh / bash / zsh (med variationer).

Svar

Jeg fandt en AWK 1-liner, og den havde en fejl, men jeg fik ordnet den. Jeg tilføjede også i PetaBytes efter 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] }") 

Overvejer stat er ikke på hvert enkelt system, du kan næsten altid bruge AWK-løsningen. Eksempel; Raspberry Pi har ikke stat men den har awk .

Kommentarer

  • Helt IKKE hvad OP anmodede, men pænt lille stykke arbejde.

Svar

Jeg kan godt lide valgmuligheden wc. Parret med “bc” kan du få decimaler så mange steder som du vil.

Jeg ledte efter at forbedre et script, jeg havde det forkert, redigerede kolonnen “filstørrelse” i en “ls – alh “kommando. Jeg ville ikke bare have helt filstørrelser, og to decimaler syntes at passe, så efter at have læst denne diskussion kom jeg op med koden nedenfor.

Jeg foreslår at bryde linjen ved semikolonerne, hvis du inkluderer dette i et 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"

Min script kaldes gpfl for “få længde på billedfil.” Jeg bruger det efter at have foretaget en mogrify på en fil i imagemagick, før jeg åbner eller genindlæser et billede i en GUI jpeg-fremviser.

Jeg ved ikke, hvordan dette vurderes som et “svar”, da det låner meget af, hvad der allerede er blevet tilbudt og diskuteret. Så jeg lader det være der.

BZT

Kommentarer

  • Jeg foretrækker at bruge ” stat ” eller ” ls ” div Typisk kan jeg ikke lide ‘ som at bruge ” wc ” for at få filstørrelser, fordi det læser fysisk hele filen. Hvis du har mange filer eller især store filer, kan det tage meget tid. Men din løsning er kreativ … + 1.
  • Jeg er enig med begrebet at bruge ” stat ” over ” wc ” til filstørrelse, men hvis du bruger ” wc -c “, læses ingen data; i stedet bruges lseek til finde ud af antallet af bytes i en fil. lingrok.org/xref/coreutils/src/wc.c#228
  • @ bbaja42 : bemærk, at GNU Coreutils læser den sidste blok i filen, hvis stat.st_size kun var en tilnærmelse (som for Linux /proc og /sys filer). Jeg antager, at de besluttede ikke at gøre hovedkommentaren mere kompliceret, da de tilføjede logikken et par linjer ned: lingrok.org/xref/coreutils/src/wc.c#246

Svar

Den hurtigste og enkleste (IMO) metode er:

bash_var=$(stat -c %s /path/to/filename) 

Kommentarer

  • Opstem derefter et eller flere af de eksisterende svar, der nævner stat; ikke nødvendigt at gentage det igen …
  • @JeffSchaller Jeg har lige opstemt Stephane ‘ s svar på dine instruktioner.Jeg synes, det er for kompliceret til mine formål. Derfor sendte jeg dette enkle svar til ligesindede sjæle.
  • Tak; det ‘ er netop, at en sjette forekomst af en ” stat ” svar forenkler ikke ‘ t denne Q & A, men vil hellere få en ny læser til at spørge sig selv ” hvordan adskiller dette svar sig fra de andre? ” og fører til mere forvirring i stedet for mindre.
  • @JeffSchaller antager jeg. Men jeg kunne klage over de mange du og wc svar, der skulle have en ansvarsfraskrivelse ALDRIG GØR DETTE i virkeligheden liv. Jeg brugte bare mit svar i en applikation fra det virkelige liv i aften og troede, det var umagen værd at dele. Jeg antager, at vi alle har vores meninger trækker på skuldrene .

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *