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
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 å sammenlignestat --printf="%s" file.any | xxd -
tilstat -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 avdu
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, dermedsize=$(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
brukerfstat
, men søker deretter den nest siste blokken av filen og leser den siste opp tilst_blksize
byte. Tilsynelatende er fordi filer i Linux ‘ s/proc
og/sys
har for eksempel statstørrelser som bare er omtrentlige , ogwc
ønsker å rapportere den faktiske størrelsen, ikke den statrapporterte størrelsen. Jeg antar at det ville være rart forwc -c
å rapportere en annen størrelse ennwc
, 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 ignorererecho
det hvite rommet. Noen måte å gjøre det konsistent på? - @keithpjolley: Ved å ringe
fstat
. Prøv å kjørestrace 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 erst_size
til filen etter symlinkoppløsning. -
zsh
stat
innebygd (nå også kjent somzstat
) izsh/stat
-modulen (lastet medzmodload 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 BusyBoxstat
siden 2 005 (kopiert fra GNUstat
):stat -c %s -- "$file" # st_size of file stat -Lc %s -- "$file" # after symlink resolution
(merk betydningen av
-L
er reversert sammenlignet med IRIX ellerzsh
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 avzsh/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
brukerfstat
, men leser deretter de siste opp tilst_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
ogstat
-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. GNUdu
bruker kibibytes i stedet med mindre det heterPOSIXLY_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
ogwc
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 .
pv
ogcat
for en kopikommando som viser fremgang og ETA 🙂-s
, så du kan bare teste om en fil har en null lengde medif [ -s file ]; then echo "file has nonzero size" ; fi