Jak mohu získat velikost souboru v bash skriptu?

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

  • stackoverflow.com/questions/5920333/how-to-check-size-of-a-file LOL pro migraci 🙂
  • Spárovat to s pv a cat příkaz pro kopírování, který zobrazuje pokrok a ETA 🙂
  • soubor stat -c% s. name
  • V případě (velmi úzkého) problému XY je to úhledné: pokud vše, co potřebujete, je otestovat, že soubor má nenulovou velikost, bash má podmíněný výraz -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

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ím stat --printf="%s" file.any | xxd - s stat -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, tedy size=$(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é , a wc chce nahlásit skutečnou velikost, nikoli velikost ohlášenou statem. Myslím, že by bylo divné, kdyby wc -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 stranu echo mezery ignoruje. Nějakým způsobem, aby to bylo konzistentní?
  • @keithpjolley: Voláním fstat. Zkuste spustit strace 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)) 

ksh93wc 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á o st_size souboru po rozlišení symbolického odkazu.

  • zsh stat builtin (nyní také známý jako zstat) v modulu zsh/stat (načteno zmodload 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 BusyBoxu stat od 2 005 (zkopírováno z GNU stat):

    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 nebo zsh 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í modulu zsh/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 „ obsah kanálu, pouhé otevření zde pojmenovaného kanálu může mít stále vedlejší účinky. Nejprve používáme 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řebujete ls -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 a stat 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. GNU du používá místo toho kibibyty, pokud nejsou volány s POSIXLY_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 a wc 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 .

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *