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
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 sammenlignestat --printf="%s" file.any | xxd -
tilstat -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 afdu
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åledessize=$(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
brugerfstat
, men søger derefter den næstsidste blok af filen og læser den sidste op tilst_blksize
byte. Tilsyneladende er fordi filer i Linux ‘ s/proc
og/sys
har for eksempel statstørrelser, der kun er omtrentlige , ogwc
ønsker at rapportere den faktiske størrelse, ikke den stat-rapporterede størrelse. Jeg antager, at det ville være underligt forwc -c
at rapportere en anden størrelse endwc
, 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 ignorererecho
det hvide område. Nogen måde at gøre det konsistent på? - @keithpjolley: Ved at ringe til
fstat
. Prøv at kørestrace 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 erst_size
af filen efter symlinkopløsning. -
zsh
stat
indbygget (nu også kendt somzstat
) izsh/stat
-modulet (indlæst medzmodload 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 BusyBoxstat
siden 2 005 (kopieret fra GNUstat
):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 ellerzsh
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 afzsh/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
brugerfstat
, men læser derefter de sidste op tilst_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 forls -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
ogstat
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. GNUdu
bruger i stedet kibibytes, medmindre det kaldes medPOSIXLY_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
ogwc
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 .
pv
ogcat
til en kopikommando, der viser fremskridt og ETA 🙂-s
, så du kan bare teste, om en fil har en nul længde medif [ -s file ]; then echo "file has nonzero size" ; fi