Jak mohu získat velikost souboru v bash skriptu?
Jak to přiřadím k proměnné bash, abych ji mohl později použít?
Komentáře
Odpovědět
Vaše nejlepší sázka v systému GNU:
stat --printf="%s" file.any
Od man stat :
% s celková velikost, v bajtech
V bash skriptu:
#!/bin/bash FILENAME=/home/heiko/dummy/packages.txt FILESIZE=$(stat -c%s "$FILENAME") echo "Size of $FILENAME = $FILESIZE bytes."
POZNÁMKA: viz
odpověď @chbrown , jak používat stat v terminálu v systému Mac OS X.
Komentáře
- @ haunted85
stat
je nejpřímější způsob za předpokladu, že ‚ používáte Linux nebo Cygwin (stat
není ‚ t standard).wc -c
jak navrhl Eug é ne je přenosný. -
stat: illegal option -- c
-
stat --printf="%s" file.txt
není ‚ t vydat cokoli na Debian Jessie … - V systému MacOS to funguje:
stat -f%z myfile.tar
- @woohoo Vaše výzva přepíše výstup.
man stat
říká, že –printf vynechává koncový nový řádek. Výstup zobrazíte pomocí--format
nebo-c
. Získejte lepší přehled porovnánímstat --printf="%s" file.any | xxd -
sstat -c "%s" file.any | xxd -
odpovědí
file_size_kb=`du -k "$filename" | cut -f1`
Problém s používáním stat
spočívá v tom, že se jedná o příponu GNU (Linux). du -k
a cut -f1
jsou specifikovány POSIXem a jsou proto přenosné do jakéhokoli systému Unix.
Například Solaris je dodáván s bash, ale ne s stat
. Není to tedy zcela hypotetické.
ls
má podobný problém v tom, že není specifikován přesný formát výstupu, takže jeho výstup nelze analyzovat přenositelně . du -h
je také příponou GNU.
Držte se přenosných konstrukcí, kde je to možné, a někomu v budoucnu usnadníte život. Možná váš vlastní.
Komentáře
-
du
neposkytuje ‚ velikost souboru, udává, kolik místa soubor využívá, což je nepatrně odlišné (obvykle velikost udávanádu
je velikost souboru zaokrouhleno nahoru na nejbližší počet bloků, přičemž blok má obvykle 512 B nebo 1 kB nebo 4 kB). - @Gilles, řídké soubory (tj. ty, které mají v sobě díry), vykazují menší délku.
- To by měla být přijatá odpověď s
--bytes
nebo-b
místo-k
. / li> - @fralau: OP chce “ přiřadit tuto proměnnou bash, aby ji mohli později použít „, takže je mnohem pravděpodobnější, že chtějí aktu al číselná hodnota, nikoli lidsky čitelná aproximace.
-h
je také příponou GNU; není to standardní - Použití du s příznakem
--apparent-size
vrátí více přesná velikost (jak je uvedeno na člověku: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
)
Odpovědět
Můžete také použít příkaz“ word count „(wc
):
wc -c "$filename" | awk "{print $1}"
Problém s wc
spočívá v tom, že přidá název souboru a odsadí výstup. Například:
$ wc -c somefile.txt 1160 somefile.txt
Pokud se chcete vyhnout zřetězení plně interpretovaného jazyka nebo editoru streamu, abyste získali počet souborů, stačí přesměrovat vstup ze souboru, aby wc
nikdy neviděl název souboru:
wc -c < "$filename"
Tento poslední formulář lze použít k nahrazení příkazů ke snadnému získání hledané hodnoty jako proměnné prostředí, jak uvádí Gilles níže.
size="$(wc -c <"$filename")"
Komentáře
-
wc -c <"$FILENAME"
udává velikost bez dalšího cruftu, tedysize=$(wc -c <"$FILENAME")
. - Ještě jeden bod: právě jsem to otestoval a
wc -c < file
se zdá být velmi rychlý, alespoň v OS X. I ‚ hádám, že wc má mozek, aby se pokusil stat soubor, pokud je zadáno pouze -c. - @EdwardFalk: GNU
wc -c
používáfstat
, ale poté hledá druhý a poslední blok souboru a přečte posledních ažst_blksize
bajtů. Zřejmě je to proto, že soubory v systému Linux ‚ s/proc
a/sys
například mají velikosti statů, které jsou pouze přibližné , awc
chce nahlásit skutečnou velikost, nikoli velikost ohlášenou statem. Myslím, že by bylo divné, kdybywc -c
hlásil jinou velikost nežwc
, ale ‚ div nemá nápad číst data ze souboru, pokud je ‚ normální soubor na disku a ‚ není v paměti. Nebo ještě horší, páskové úložiště blízkého řádku … - Zdá se, že
printf
stále vidí odsazení, např.printf "Size: $size"
– >size: <4 spaces> 54339
. Na druhou stranuecho
mezery ignoruje. Nějakým způsobem, aby to bylo konzistentní? - @keithpjolley: Voláním
fstat
. Zkuste spustitstrace wc -c </etc/passwd
a uvidíte, co dělá.
Odpovědět
BSD (s macOS) stat
má jiný příznak argumentu formátu a různé specifikátory polí. Z man stat(1)
:
-
-f format
: Zobrazovat informace v zadaném formátu. Popis platných formátů najdete v sekci FORMATS. - … sekce FORMATS …
-
z
: Velikost soubor v bajtech.
Takže teď všichni dohromady:
stat -f%z myfile1.txt
POZNÁMKA: viz Odpověď @ b01 , jak používat příkaz stat
v systémech GNU / Linux. 🙂
Komentáře
- Upozorňujeme, že toto je řešení pouze pro BSD. ‚ nefunguje s GNU
stat
, bohužel.
Odpovědět
Závisí to na tom, co myslíte velikostí .
size=$(wc -c < "$file")
vám poskytne počet bajtů, které lze ze souboru načíst. IOW, je to velikost obsahu souboru. Přečte však obsah souboru (kromě případů, kdy se jedná o běžný soubor nebo o symbolický odkaz na běžný soubor ve většině implementací wc
jako optimalizace). To může mít vedlejší účinky. Například u pojmenovaného kanálu již nelze přečíst to, co bylo načteno, a u věcí jako /dev/zero
nebo /dev/random
které jsou nekonečná velikost, bude to chvíli trvat. To také znamená, že potřebujete read
oprávnění k souboru a poslední časové razítko souboru může být aktualizováno.
Jedná se o standardní a přenosné zařízení, ale uvědomte si, že některé implementace wc
mohou v tomto výstupu obsahovat mezery. Jedním ze způsobů, jak se jich zbavit, je použít:
size=$(($(wc -c < "$file")))
nebo vyhnout se chybě ohledně prázdného aritmetického výrazu v dash
nebo yash
když wc
neprodukuje žádný výstup (například když nelze soubor otevřít):
size=$(($(wc -c < "$file") +0))
ksh93
má wc
zabudováno (pokud to povolíte, můžete jej také vyvolat jako command /opt/ast/bin/wc
), což je nejúčinnější pro běžné soubory v tomto prostředí.
Různé systémy mají příkaz s názvem stat
, které je rozhraním k stat()
nebo lstat()
systémovým voláním.
Tyto informace přehledu nalezené v inode. Jednou z těchto informací je atribut st_size
. U běžných souborů to je velikost obsahu (kolik dat z něj lze načíst bez chyby (to je to, co většina wc -c
implementací používá při své optimalizaci) ). U symbolických odkazů to je velikost v bajtech cílové cesty. U pojmenovaných kanálů je to v závislosti na systému buď 0, nebo počet bytů aktuálně ve vyrovnávací paměti kanálu. Totéž platí pro bloková zařízení, kde v závislosti na systému získáte 0 nebo velikost základního úložiště v bajtech.
K získání těchto informací nepotřebujete oprávnění ke čtení souboru, pouze oprávnění k vyhledávání adresář, na který je propojen.
V chronologickém pořadí je:
-
IRIX
stat
(90 „s):stat -qLs -- "$file"
vrátí atribut
st_size
z$file
(lstat()
) nebo:stat -s -- "$file"
stejné, kromě případů, kdy
$file
je symbolický odkaz, v takovém případě se jedná ost_size
souboru po rozlišení symbolického odkazu. -
zsh
stat
builtin (nyní také známý jakozstat
) v moduluzsh/stat
(načtenozmodload zsh/stat
) (1997):stat -L +size -- $file # st_size of file stat +size -- $file # after symlink resolution
nebo uložit do proměnné:
stat -L -A size +size -- $file
to je samozřejmě nejúčinnější v ten shell.
-
GNU
stat
(2001); také v BusyBoxustat
od 2 005 (zkopírováno z GNUstat
):stat -c %s -- "$file" # st_size of file stat -Lc %s -- "$file" # after symlink resolution
(všimněte si významu
-L
je obrácen ve srovnání s IRIX nebozsh
stat
. -
BSD
stat
(2002):stat -f %z -- "$file" # st_size of file stat -Lf %z -- "$file" # after symlink resolution
Nebo můžete použít funkci stat()
/ lstat()
některého skriptovacího jazyka, jako je perl
:
perl -le "print((lstat shift)[7])" -- "$file"
AIX má také istat
příkaz , který vypíše všechny stat()
(ne lstat()
, takže nebude pracovat na symbolických odkazech ) informace a které byste mohli následně zpracovat, například:
LC_ALL=C istat "$file" | awk "NR == 4 {print $5}"
(díky @JeffSchaller za pomoc při zjišťování podrobností ).
V tcsh
:
@ size = -Z $file:q
(velikost po rozlišení symbolického odkazu)
Dlouho předtím, než GNU představil svůj stat
příkaz, stejného lze dosáhnout s GNU find
příkaz s -printf
predikátem (již v roce 1991):
find -- "$file" -prune -printf "%s\n" # st_size of file find -L -- "$file" -prune -printf "%s\n" # after symlink resolution
Jedním z problémů však je, že fungovat, pokud $file
začíná -
nebo je find
predikátem (jako !
, (
…).
Standardní příkaz k získání stat()
/ lstat()
informace jsou ls
.
POSIXově můžete:
LC_ALL=C ls -dn -- "$file" | awk "{print $5; exit}"
a přidat -L
pro stejné po rozlišení symbolických odkazů. To nefunguje pro soubory zařízení, i když je místo jejich velikosti 5. th hlavní číslo zařízení.
U blokových zařízení systémy, kde stat()
vrací 0 pro st_size
, obvykle má jiná rozhraní API, která hlásí velikost blokového zařízení. Například Linux má BLKGETSIZE64
ioctl()
a většina distribucí systému Linux se nyní dodává s příkazem blockdev
, který jej může využít:
blockdev --getsize64 -- "$device_file"
K tomu však potřebujete oprávnění ke čtení souboru zařízení. Obvykle je možné odvodit velikost jinými prostředky. Například (stále v systému Linux):
lsblk -bdno size -- "$device_file"
Měl by fungovat kromě prázdných zařízení.
Přístup, který funguje pro všechny viditelné soubory (tedy zahrnuje běžné soubory, většinu blokových zařízení a některá znaková zařízení) je otevřít soubor a usilovat o konec:
-
S
zsh
(po načtení moduluzsh/system
):{sysseek -w end 0 && size=$((systell(0)))} < $file
-
S
ksh93
:< "$file" <#((size=EOF))
nebo
{ size=$(<#((EOF))); } < "$file"
-
s
perl
:perl -le "seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN" < "$file"
U pojmenovaných kanálů jsme zjistili, že některé systémy (alespoň AIX, Solaris, HP / UX) zpřístupňují množství dat ve vyrovnávací paměti kanálu v stat()
„s st_size
. Někteří (například Linux nebo FreeBSD) to nedokáží.
Minimálně v systému Linux můžete použít FIONREAD
ioctl()
po otevření kanálu (v režimu čtení + zápis, aby se zabránilo jeho zavěšení):
fuser -s -- "$fifo_file" && perl -le "require "sys/ioctl.ph"; ioctl(STDIN, &FIONREAD, $n) or die$!; print unpack "L", $n" <> "$fifo_file"
Mějte však na paměti, že i když to „fuser
, abychom nejprve zkontrolovali, zda některý proces již má otevřenou trubku, abychom to zmírnili, ale to není zcela bezpečné, protože fuser
může nebudeme moci zkontrolovat všechny procesy.
Nyní jsme zatím uvažovali pouze o velikosti primárních dat přidružených k souborům.To nebere v úvahu velikost metadat a veškerou podpůrnou infrastrukturu potřebnou k uložení tohoto souboru.
Další atribut inode vrácený stat()
je st_blocks
. To je počet 512 bajtových bloků, které se používají k ukládání dat souboru (a někdy některá jeho metadata, jako jsou rozšířené atributy v souborových systémech ext4 v systému Linux). „Nezahrnuje samotný inode nebo položky v adresářích, se kterými je soubor propojen.
Velikost a využití disku nemusí nutně úzce souviset jako komprese, řídkost (někdy některá metadata), zvláštní infrastruktura jako nepřímé bloky v některých souborových systémech na ně má vliv.
To je obvykle to, co du
používá k hlášení využití disku. Většina výše uvedených příkazů bude schopna získáte tyto informace.
-
POSIXLY_CORRECT=1 ls -sd -- "$file" | awk "{print $1; exit}"
-
POSIXLY_CORRECT=1 du -s -- "$file"
(neplatí pro adresáře kde by to zahrnovalo použití disku e souborů uvnitř). - 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"
Komentáře
- jednoznačně nejkomplexnější a nejinformativnější odpověď. Děkuji. Mohu to použít k vytvoření multiplatformních bash skriptů pomocí statistik BSD a GNU.
- Zábavný fakt: GNU coreutils
wc -c
používáfstat
, ale poté načte posledních ažst_blksize
bajtů. Zřejmě je to proto, že soubory v systému Linux ‚ s/proc
a/sys
například mají velikosti statů, které jsou pouze přibližné . To je dobré pro správnost, ale špatné, pokud je konec souboru na disku a ne v paměti (zejména pokud je použit na mnoha souborech ve smyčce). A velmi špatné, pokud je soubor migrován na úložiště na pásku v blízkosti řádku , nebo např. transparentní dekompresní souborový systém FUSE. - to by také nefungovalo
ls -go file | awk '{print $3}'
- @StevenPenny ty
-go
by byly ty SysV, nepracovaly by ‚ na BSD (volitelně (XSI) v POSIXu). ‚ d také potřebujetels -god file | awk '{print $3; exit}'
(-d
, aby fungoval v adresářích,exit
pro symbolické odkazy s novými řádky v cíli). Rovněž přetrvávají problémy se soubory zařízení. - @ αғsнιη Unix API nerozlišuje mezi textovými a binárními soubory. ‚ obsahuje všechny sekvence bajtů. Některé aplikace mohou chtít tyto bajty interpretovat jako text, ale zjevně ne
wc -c
který uvádí počet bajtů.
Odpovědět
Tento skript kombinuje mnoho způsobů výpočtu velikosti souboru:
( 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}"
Skript funguje na mnoha systémech Unix včetně Linux, BSD, OSX, Solaris, SunOS atd.
Velikost souboru ukazuje počet bajtů. Je to zdánlivá velikost, což jsou bajty, které soubor používá na typickém disku, bez speciální komprese nebo zvláštních řídkých oblastí nebo nepřidělených bloků atd.
Tento skript má produkční verzi s další pomocí a více možností zde: https://github.com/SixArm/file-size
Odpovědět
stat to dělá s nejmenším počtem systémových volání:
$ 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
Odpověď
ls -l filename
vám poskytne spoustu informací o souboru, včetně jeho velikosti, oprávnění a vlastníka.
Velikost souboru v pátém sloupci a je zobrazena v bajtech. V níže uvedeném příkladu je velikost souboru těsně pod 2 kB:
-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php
Upravit: To zjevně není tak spolehlivé jako příkaz stat
.
Komentáře
- Myslím, že příkaz
ls -l
astat
poskytují spolehlivé informace o velikosti. Nenašel jsem žádný odkaz na opak.ls -s
udá velikost v počtu bloků. - @ dabest1 ‚ to není spolehlivé v tom smyslu, že v jiný unix, jejich výstup může být odlišný (a v některých unixech ano).
- Ano, IIRC, Solaris ve výchozím nastavení nezobrazil název skupiny, což vede k menšímu počtu sloupců ve výstupu.
- Jelikož velikost je čistě číselná, obklopená mezerami a rok data je čistě číselný, v definovaném formátu by bylo možné použít k úpravě uživatele regexp + vlastník jako jedno pole, bez ohledu na to, zda byla skupina přítomna. (cvičení pro čtenáře!)
Odpověď
du filename
vám řekne využití disku v bajtech.
Dávám přednost du -h filename
, který vám dává velikost v čitelném formátu.
Komentáře
- že nebo
stat -c "%s"
😉 - Tato příchuť
du
vytiskne velikost v blocích 1024 bajtů, ne jednoduchý počet bajtů. - Upozorňujeme, že standardní
du
poskytuje výstup v počtu 512 bajtových jednotek. GNUdu
používá místo toho kibibyty, pokud nejsou volány sPOSIXLY_CORRECT
v jeho prostředí. - Pro soubory typu adresář , která udává využití disku v adresáři, ale také ve všech ostatních souborech v něm (rekurzivně).
Odpověď
Vytvořte ve svých skriptech prostředí malé obslužné funkce, na které můžete delegovat.
Příklad
#! /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
Na základě informací od @ Stéphane Chazelas „odpověď.
Komentáře
- Viz také
gzip -v < file > /dev/null
ke kontrole stlačitelnosti souboru. - @St é phaneChazelas si nejsem jistý, jestli si myslím, že to bylo vylepšení. tyto výroky případu mohou noobs snadno odradit; rozhodně si nikdy nepamatuji, jak je napravit 🙂 jsou výroky případů neodmyslitelně přenosnější, protože ty viděl jsem to, když existují více než dva případy, ale jinak … +
- Předpokládám, že ‚ s je také věcí vkusu, ale tady je ‚ typický případ, kdy ‚ chcete použít
case
prohlášení.case
je konstrukt Bourne / POSIX pro porovnávání vzorů.[[...]]
je pouze ksh / bash / zsh (s variantami).
Odpověď
Našel jsem vložka AWK 1 a měla chybu, ale opravil jsem ji. Také jsem přidal do PetaBytes po 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] }")
Vzhledem k stat není v každém systému, řešení AWK můžete použít téměř vždy. Příklad; Raspberry Pi nemá stat , ale awk .
Komentáře
- Zcela NENÍ to, co OP požadoval, ale pěkný kousek práce.
Odpověď
Sám se mi líbí volba wc. Spárované s „bc“, můžete získat desetinná místa na tolik míst, kolik chcete.
Chtěl jsem vylepšit skript, který jsem po tomto awk „vyřadil ve sloupci“ ls – sloupec „velikost souboru“ – alh „příkaz. Nechtěl jsem jen celočíselné velikosti souborů a dvě desetinná místa se zdají vyhovovat, takže po přečtení této diskuse jsem přišel s níže uvedeným kódem.
Navrhuji přerušit čáru na středníky, pokud to zahrnete do skriptu.
file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"
Moje skript se nazývá gpfl pro „získat délku obrazového souboru“. Používám jej po mogrify na souboru v imagemagick, před otevřením nebo opětovným načtením obrázku v prohlížeči jpeg v GUI.
Nevím, jak to hodnotím jako „odpověď“, protože si hodně půjčuje z toho, co již bylo nabídnuto a diskutováno. Takže to tam nechám.
BZT
Komentáře
- Dávám přednost použití “ stat “ nebo “ ls „. Obvykle se mi ‚ nelíbí používat “ wc “ získávat velikosti souborů, protože fyzicky přečte celý soubor. Pokud máte spoustu souborů nebo obzvláště velké soubory, může to trvat hodně času. Ale vaše řešení je kreativní … + 1.
- Souhlasím s představou používání “ stat “ nad “ wc “ pro velikost souboru, ale pokud použijete “ wc -c „, nebudou se číst žádná data; místo toho se použije lseek zjistit počet bajtů v souboru. lingrok.org/xref/coreutils/src/wc.c#228
- @ bbaja42 : všimněte si, že GNU Coreutils přečte poslední blok souboru pro případ, že by
stat.st_size
byla pouze přibližná (jako pro Linux/proc
a/sys
soubory). Myslím, že se rozhodli nezkomplikovat hlavní komentář, když přidali tuto logiku o pár řádků dolů: lingrok.org/xref/coreutils/src/wc.c#246
Odpověď
Nejrychlejší a nejjednodušší (IMO) metoda je:
bash_var=$(stat -c %s /path/to/filename)
Komentáře
- Poté hlasujte pro jednu nebo více existujících odpovědí, které zmiňují stat; není třeba to opakovat znovu …
- @JeffSchaller Právě jsem hlasoval pro odpověď Stephane ‚ s vašimi pokyny.Myslím, že je to pro mé účely příliš komplikované. Proto jsem zveřejnil tuto jednoduchou odpověď pro stejně smýšlející duše.
- Děkuji; jde ‚ pouze o to, že šestá instance “ stat “ odpověď to ‚ t nezjednodušuje Q & A, ale raději by přimělo nového čtenáře, aby si položil otázku “ v čem se tato odpověď liší od ostatních? “ a vede k většímu zmatku místo k menšímu.
- @JeffSchaller. Mohl bych si ale stěžovat na mnoho
du
awc
odpovědí, které by měly mít zřeknutí se odpovědnosti NIKDY TO NEPOUŽÍVEJTE život. Právě jsem dnes v noci použil svou odpověď v reálné aplikaci a myslel jsem si, že to stojí za sdílení. Myslím, že každý máme své názory pokrčí rameny .
pv
acat
příkaz pro kopírování, který zobrazuje pokrok a ETA 🙂-s
, takže můžete jednoduše otestovat, zda má soubor nenulovou délku pomocíif [ -s file ]; then echo "file has nonzero size" ; fi