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

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

Hvordan tilordner jeg dette til en bash-variabel slik at jeg kan bruke den senere?

Kommentarer

  • stackoverflow.com/questions/5920333/how-to-check-size-of-a-file LOL for migrate 🙂
  • Koble dette med pv og cat for en kopikommando som viser fremgang og ETA 🙂
  • stat -c% s-fil. navn
  • I tilfelle (veldig smalt) XY-problem, er dette pent: hvis alt du trenger er å teste filen har en null-størrelse, har bash et betinget uttrykk -s, så du kan bare teste om en fil har en null lengde med if [ -s file ]; then echo "file has nonzero size" ; fi

Svar

Det beste alternativet hvis du bruker et GNU-system:

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

Fra mannstat :

% s totalstørrelse, i byte

I et bash-skript:

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

MERK: se

@chbrowns svar for hvordan du bruker stat i terminal på Mac OS X.

Kommentarer

  • @ haunted85 stat er den enkleste måten, forutsatt at du ‘ bruker Linux eller Cygwin (stat isn ‘ t standard). wc -c som foreslått av Eug é ne er bærbar.
  • stat: illegal option -- c
  • stat --printf="%s" file.txt ikke ‘ t send ut noe på Debian Jessie …
  • På MacOS fungerer dette: stat -f%z myfile.tar
  • @woohoo Din ledetekst overskriver utdataene. man stat sier at –printf utelater den etterfølgende nye linjen. Bruk --format eller -c for å se utdataene. Få mer innsikt ved å 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 å bruke stat er at det er en GNU (Linux) -utvidelse. du -k og cut -f1 er spesifisert av POSIX og er derfor bærbare til ethvert Unix-system.

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

ls har et lignende problem ved at det eksakte formatet på utdataene ikke er spesifisert, så å analysere utdataene kan ikke gjøres bærbart . du -h er også en GNU-utvidelse.

Hold deg til bærbare konstruksjoner der det er mulig, og du vil gjøre det lettere for noen i fremtiden. Kanskje din egen.

Kommentarer

  • du gir ikke ‘ t størrelsen på filen, det gir en indikasjon på hvor mye plass filen bruker, som er subtilt forskjellig (vanligvis er størrelsen rapportert av du størrelsen på filen avrundet opp til nærmeste antall blokker, hvor en blokk vanligvis er 512B eller 1kB eller 4kB).
  • @ Gilles, sparsomme filer (dvs. filer med hull i) rapporterer mindre enn lengden.
  • Dette, med --bytes eller -b i stedet for -k, bør være det aksepterte svaret.
  • @fralau: OP vil » tildele dette til en bash-variabel slik at de kan bruke den senere «, så det er mye mer sannsynlig at de vil ha en aktu en numerisk verdi, ikke en menneskelig lesbar tilnærming. -h er også en GNU-utvidelse; det er ikke standard
  • Bruk av du med --apparent-size flagg vil returnere en mer presis størrelse (som angitt på mannen: 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å bruke kommandoen» ordtelling «(wc):

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

Problemet med wc er at det «legger til filnavnet og innrykk utdataene. For eksempel:

$ wc -c somefile.txt 1160 somefile.txt 

Hvis du vil unngå å koble et fullstendig tolket språk eller strømredigerer bare for å få en filstørrelse, er det bare å omdirigere inngangen fra filen slik at wc aldri ser filnavnet:

wc -c < "$filename" 

Dette siste skjemaet kan brukes med kommandosubstitusjon for enkelt å hente verdien du søkte som en skallvariabel, som nevnt av Gilles nedenfor.

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

Kommentarer

  • wc -c <"$FILENAME" gir størrelsen uten annen cruft, dermed size=$(wc -c <"$FILENAME").
  • Bare ett poeng til: Jeg har nettopp testet det og wc -c < file ser ut til å være veldig raskt, i det minste på OS X. I ‘ Jeg gjetter at wc har hjernen til å prøve å statere filen hvis bare -c er spesifisert.
  • @EdwardFalk: GNU wc -c bruker fstat, men søker deretter den nest siste blokken av filen og leser den siste opp til st_blksize byte. Tilsynelatende er fordi filer i Linux ‘ s /proc og /sys har for eksempel statstørrelser som bare er omtrentlige , og wc ønsker å rapportere den faktiske størrelsen, ikke den statrapporterte størrelsen. Jeg antar at det ville være rart for wc -c å rapportere en annen størrelse enn wc, men det ‘ er ikke ideen om å lese data fra filen hvis den ‘ er en normal diskfil, og den ‘ ikke er i minnet. Eller verre, nærlinjebåndlagring …
  • Det virker som printf fremdeles ser fordypningen, f.eks. printf "Size: $size" – > size: <4 spaces> 54339. På den annen side ignorerer echo det hvite rommet. Noen måte å gjøre det konsistent på?
  • @keithpjolley: Ved å ringe fstat. Prøv å kjøre strace wc -c </etc/passwd, og du kan se hva den gjør.

Svar

BSD «s (macOS» s) stat har et annet formatargumentflagg og forskjellige feltangivere. Fra man stat(1):

  • -f format: Vis informasjon i det angitte formatet. Se FORMATER-delen for en beskrivelse av gyldige formater.
  • … FORMATS-delen …
  • z: Størrelsen på fil i byte.

Så alt sammen nå:

stat -f%z myfile1.txt 

MERK: se @ b01 «svar for hvordan du bruker kommandoen stat på GNU / Linux-systemer. 🙂

Kommentarer

  • Merk at dette er en bare BSD-løsning. Det fungerer ikke ‘ med GNU stat dessverre.

Svar

Avhenger av hva du mener med størrelse .

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

gir deg antall byte som kan leses fra filen. IOW, den er størrelsen på innholdet i filen. Den vil imidlertid lese innholdet i filen (unntatt hvis filen er en vanlig fil eller symlink til vanlig fil i de fleste wc implementeringer som en optimalisering). Det kan ha bivirkninger. For eksempel, for et navngitt rør, kan det som er lest ikke lenger leses igjen og for ting som /dev/zero eller /dev/random som er av uendelig størrelse, det tar litt tid. Det betyr også at du trenger read tillatelse til filen, og siste tidsstempel for filen kan oppdateres.

Det er standard og bærbart, men vær oppmerksom på at noen wc -implementeringer kan inkludere ledende blanke i utgangen. En måte å kvitte seg med dem er å bruke:

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

eller å unngå en feil om et tomt aritmetisk uttrykk i dash eller yash når wc gir ingen utdata (som når filen ikke kan åpnes):

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

ksh93 har wc innebygd (forutsatt at du aktiverer det, kan du også påberope det som command /opt/ast/bin/wc) som gjør det mest effektivt for vanlige filer i det skallet.

Ulike systemer har en kommando kalt stat som er et grensesnitt til stat() eller lstat() systemanrop.

Disse rapportinformasjonene som finnes i inode. En av denne informasjonen er st_size attributtet. For vanlige filer, som er størrelsen på innholdet (hvor mye data kan leses fra det i fravær av feil (det er det de fleste wc -c implementeringer bruker i optimaliseringen) ). For symlinker, som er størrelsen i byte på målbanen. For navngitte rør, avhengig av systemet, er det enten 0 eller antall byte som for tiden er i rørbufferen. Samme for blokkeringsenheter der du, avhengig av systemet, får 0 eller størrelsen i byte på den underliggende lagringen.

Du trenger ikke lesetillatelse til filen for å få den informasjonen, bare søk tillatelse til katalog det er knyttet til.

Etter kronologisk rekkefølge er det:

  • IRIX stat (90 «s):

    stat -qLs -- "$file" 

    returnerer st_size attributtet til $file (lstat()) eller:

    stat -s -- "$file" 

    samme bortsett fra når $file er en symlink i hvilket tilfelle den er st_size til filen etter symlinkoppløsning.

  • zsh stat innebygd (nå også kjent som zstat) i zsh/stat -modulen (lastet med zmodload zsh/stat) (1997):

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

    eller å lagre i en variabel:

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

    åpenbart, det er det mest effektive i det skallet.

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

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

    (merk betydningen av -L er reversert sammenlignet med IRIX eller zsh stat.

  • BSDs stat (2002):

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

Eller du kan bruke stat() / lstat() -funksjonen til et skriptspråk som perl:

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

AIX har også en istat -kommando som vil dumpe all stat() (ikke lstat(), så vil ikke arbeidet med symlinker ) informasjon og som du kan etterbehandle med, for eksempel:

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

(takk @JeffSchaller for hjelp til å finne ut detaljene ).

I tcsh:

@ size = -Z $file:q 

(størrelse etter symlinkoppløsning)

Langt før GNU introduserte kommandoen stat, kunne det samme oppnås med GNU find kommando med sitt -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 imidlertid at det ikke fungerer hvis $file starter med - eller er et find predikat (som !, ( …).

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

POSIX, du kan gjøre:

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

og legg til -L for det samme etter symlinkoppløsning. Det fungerer ikke for enhetsfiler, men der 5 th -feltet er enhetens hovednummer i stedet for størrelsen.

For blokkeringsenheter, systemer der stat() returnerer 0 for st_size, har vanligvis andre API-er for å rapportere størrelsen på blokkenheten. For eksempel har Linux BLKGETSIZE64 ioctl(), og de fleste Linux-distribusjoner leveres nå med en blockdev -kommando som kan gjøre bruk av den:

blockdev --getsize64 -- "$device_file" 

Du må imidlertid lese tillatelse til enhetsfilen for det. Det er vanligvis mulig å utlede størrelsen på annen måte. For eksempel (fremdeles på Linux):

lsblk -bdno size -- "$device_file" 

Bør fungere bortsett fra tomme enheter.

En tilnærming som fungerer for alle søkbare filer (inkluderer også vanlige filer, de fleste blokkeringsenheter og noen karakterenheter) er å åpne filen og søke til slutten:

  • Med zsh (etter innlasting av zsh/system -modulen):

    {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 navngitte rør har vi sett at noen systemer (AIX, Solaris, HP / UX i det minste) gjør datamengden i rørbufferen tilgjengelig i stat() «s st_size. Noen (som Linux eller FreeBSD) gjør ikke det.

I det minste på Linux kan du bruke FIONREAD ioctl() etter å ha åpnet røret (i lese + skrivemodus for å unngå at det henger):

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

Vær imidlertid oppmerksom på at mens det ikke «t leser innholdet av røret, kan bare åpningen av det navngitte røret her fortsatt ha bivirkninger. Vi bruker fuser for å sjekke først at en eller annen prosess allerede har røret åpen for å lindre det, men at det ikke er idiotsikkert som fuser ikke være i stand til å sjekke alle prosesser.

Nå, så langt har vi bare vurdert størrelsen på primære dataene som er knyttet til filene.Det tar ikke hensyn til størrelsen på metadataene og all støttende infrastruktur som er nødvendig for å lagre filen.

Et annet inode-attributt som returneres av stat() er st_blocks. Det er antallet 512 byteblokker som brukes til å lagre filens data (og noen ganger noen av dens metadata som de utvidede attributtene på ext4-filsystemer på Linux). «t inkluderer selve inoden, eller oppføringene i katalogene filen er koblet til.

Størrelse og diskbruk er ikke nødvendigvis tett knyttet til komprimering, sparshet (noen ganger noen metadata), ekstra infrastruktur som indirekte blokker i noen filsystemer har innflytelse på sistnevnte.

Det er vanligvis det du bruker for å rapportere diskbruk. De fleste av kommandoene som er oppført ovenfor vil kunne få den informasjonen.

  • POSIXLY_CORRECT=1 ls -sd -- "$file" | awk "{print $1; exit}"
  • POSIXLY_CORRECT=1 du -s -- "$file" (ikke for kataloger hvor det vil inkludere disk usag e av filene i).
  • 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 svaret. Takk skal du ha. Jeg kan bruke dette til å lage bash-skript på tvers av plattformer ved hjelp av BSD- og GNU-statistikkinformasjon
  • Morsomt faktum: GNU-kjernefiler wc -c bruker fstat, men leser deretter de siste opp til st_blksize byte. Tilsynelatende er fordi filer i Linux ‘ s /proc og /sys har for eksempel statstørrelser som bare er omtrentlige . Dette er bra for korrekthet, men dårlig hvis slutten av filen er på disken og ikke i minnet (spesielt hvis den brukes på mange filer i en løkke). Og veldig dårlig hvis filen migreres til tape-lagring nær linjen , eller f.eks. et FUSE transparent-dekomprimeringsfilsystem.
  • ville ikke dette arbeidet også ls -go file | awk '{print $3}'
  • @StevenPenny de -go ville være SysV-ene, de ville ikke ‘ t jobbe med BSD-er (valgfritt (XSI) i POSIX). Du ‘ d trenger også ls -god file | awk '{print $3; exit}' (-d for at den skal fungere i kataloger, exit for symlenker med nye linjer i målet). Problemene med enhetsfiler forblir også.
  • @ αғsнιη Unix API skiller ikke mellom tekst og binære filer. Det ‘ er alle sekvenser av byte. Noen applikasjoner vil kanskje tolke disse byte som tekst, men åpenbart ikke wc -c som rapporterer antall byte.

Svar

Dette skriptet kombinerer mange måter å 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}" 

Skriptet fungerer på mange Unix-systemer inkludert Linux, BSD, OSX, Solaris, SunOS, etc.

Filstørrelsen viser antall byte. Det er den tilsynelatende størrelsen, som er byte filen bruker på en typisk disk, uten spesiell komprimering, eller spesielle sparsomme områder, eller ikke tildelte blokker osv.

Dette skriptet har en produksjonsversjon med mer hjelp og flere alternativer her: https://github.com/SixArm/file-size

Svar

stat ser ut til å gjøre dette med færrest systemanrop:

$ 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 gir deg mye informasjon om en fil, inkludert filstørrelse, tillatelser og eier.

Filstørrelsen i den femte kolonnen, og vises i byte. I eksemplet nedenfor er filstørrelsen litt under 2 KB:

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

Rediger: Dette er tilsynelatende ikke så pålitelig som stat -kommandoen.

Kommentarer

  • Jeg tror både ls -l og stat -kommandoen gir pålitelig størrelseinformasjon. Jeg fant ingen henvisning til det motsatte. ls -s vil gi størrelse i antall blokker.
  • @ dabest1 det ‘ er ikke pålitelig i en forstand en annen unix, deres produksjon kan være annerledes (og i noen unixer er den det.).
  • Ja, IIRC, Solaris viste ikke ‘ t gruppenavnet som standard, fører til færre kolonner i utdataene.
  • Siden størrelsen er ren numerisk, omgitt av hvitt mellomrom, og datoåret er rent numerisk, i et definert format, ville det være mulig å bruke en regexp for å behandle brukeren + eier som ett felt, uansett om gruppen var tilstede eller ikke. (en øvelse for leseren!)

Svar

du filename vil fortelle deg diskbruk i byte.

Jeg foretrekker du -h filename, som gir deg størrelsen i et lesbart format.

Kommentarer

  • det eller stat -c "%s"😉
  • Denne smaken av du skriver ut størrelse i blokker av 1024 byte, ikke et enkelt antall byte.
  • Merk at standard du gir en effekt i antall 512 byte enheter. GNU du bruker kibibytes i stedet med mindre det heter POSIXLY_CORRECT i omgivelsene.
  • For filer av typen katalog , som gir diskbruk av katalogen, men også av alle de andre filene i (rekursivt).

Svar

Opprett små verktøyfunksjoner i skallskriptene 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 

Basert på info fra @ Stéphane Chazelas «svar.

Kommentarer

  • Se også gzip -v < file > /dev/null for å sjekke komprimerbarheten til en fil.
  • @St é phaneChazelas er ikke sikker på om jeg tror det var en forbedring. disse saksuttalelsene kan lett utsette noobs; Jeg husker absolutt aldri hvordan jeg skal få dem til rette 🙂 er saksuttalelser iboende mer bærbare siden du skjønte jeg poenget når det er mer enn to tilfeller, men ellers … +
  • Jeg antar at det ‘ også er et spørsmål om smak, men her er det ‘ det typiske tilfellet der du ‘ d vil bruke en case uttalelse. case er Bourne / POSIX-konstruksjonen for å gjøre mønstermatching. [[...]] er bare ksh / bash / zsh (med variasjoner).

Svar

jeg fant en AWK 1-liner, og den hadde en feil, men jeg fikset den. Jeg la også til i PetaBytes etter 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] }") 

Tatt i betraktning stat er ikke på hvert eneste system, du kan nesten alltid bruke AWK-løsningen. Eksempel; Raspberry Pi har ikke stat men den har awk .

Kommentarer

  • Helt IKKE det OP spurte, men hyggelig lite arbeid.

Svar

Jeg liker wc-alternativet selv. Parret med «bc» kan du få desimaler til så mange steder du vil.

Jeg ønsket å forbedre et skript jeg hadde som forkert, redigerte kolonnen «filstørrelse» i en «ls – alh «kommando. Jeg ønsket ikke bare heltall filstørrelser, og to desimaler så ut til å passe, så etter å ha lest denne diskusjonen, kom jeg opp med koden nedenfor.

Jeg foreslår at du bryter linjen ved semikolonene hvis du inkluderer dette i et skript.

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 skript kalles gpfl , for «få lengden på bildefilen.» Jeg bruker den etter å ha gjort en mogrify på en fil i imagemagick, før jeg åpner eller laster inn et bilde på nytt i en GUI jpeg-visning.

Jeg vet ikke hvordan dette vurderes som et «svar», ettersom det låner mye av det som allerede er tilbudt og diskutert. Så jeg lar den være der.

BZT

Kommentarer

  • Jeg foretrekker å bruke » stat » eller » ls » div Vanligvis liker jeg ikke ‘ å bruke » wc » for å få filstørrelser fordi den leser fysisk hele filen. Hvis du har mange filer, eller spesielt store filer, kan dette ta mye tid. Men løsningen din er kreativ … + 1.
  • Jeg er enig i forestillingen av å bruke » stat » over » wc » for filstørrelse, men hvis du bruker » wc -c «, vil ingen data bli lest; i stedet lseek vil bli brukt til finne ut antall byte i en fil. lingrok.org/xref/coreutils/src/wc.c#228
  • @ bbaja42 : merk at GNU Coreutils leser den siste blokken av filen, hvis stat.st_size bare var en tilnærming (som for Linux /proc og /sys filer). Jeg antar at de bestemte seg for ikke å gjøre hovedkommentaren mer komplisert da de la til logikken et par linjer ned: lingrok.org/xref/coreutils/src/wc.c#246

Svar

Raskeste og enkleste (IMO) metode er:

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

Kommentarer

  • Oppstem så et eller flere av de eksisterende svarene som nevner stat; ikke nødvendig å gjenta det igjen …
  • @JeffSchaller Jeg oppstemte bare Stephane ‘ sitt svar på instruksjonene dine.Jeg synes det er for komplisert for mine formål. Derfor la jeg ut dette enkle svaret for likesinnede sjeler.
  • Takk skal du ha; det ‘ er bare at en sjette forekomst av en » stat » svar forenkler ikke ‘ t & A, men vil heller få en ny leser til å spørre seg selv » hvordan er dette svaret forskjellig fra de andre? » og fører til mer forvirring i stedet for mindre.
  • @JeffSchaller antar jeg. Men jeg kunne klage på de mange du og wc svarene som burde ha en ansvarsfraskrivelse ALDRI GJØRE DETTE i virkeligheten liv. Jeg brukte nettopp svaret mitt i en applikasjon i virkeligheten i kveld og syntes det var verdt å dele. Jeg antar at vi alle har våre meninger trekker på skuldrene .

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *