Jak mogę uzyskać rozmiar pliku w skrypcie bash?
Jak przypisać to do zmiennej bash, aby móc jej później użyć?
pvi catdla polecenia kopiowania, które pokazuje postęp i ETA :)
Jak mogę uzyskać rozmiar pliku w skrypcie bash?
Jak przypisać to do zmiennej bash, aby móc jej później użyć?
pvi catdla polecenia kopiowania, które pokazuje postęp i ETA :)
Odpowiedzi:
Twój najlepszy zakład, jeśli w systemie GNU:
stat --printf="%s" file.any
Całkowity rozmiar% s, w bajtach
W skrypcie bash:
#!/bin/bash
FILENAME=/home/heiko/dummy/packages.txt
FILESIZE=$(stat -c%s "$FILENAME")
echo "Size of $FILENAME = $FILESIZE bytes."
UWAGA: patrz odpowiedź @ chbrown, aby dowiedzieć się, jak używać statystyki w terminalu w systemie Mac OS X.
statjest najprostszym sposobem, zakładając, że używasz Linuksa lub Cygwina ( statnie jest standardem). wc -cjak sugeruje Eugéne, jest przenośny.
stat: illegal option -- c
stat --printf="%s" file.txtnie
stat -f%z myfile.tar
man statmówi, że --printf pomija końcowy znak nowej linii. Użyj --formatlub, -caby zobaczyć wynik. Zyskaj więcej wglądu w porównaniu stat --printf="%s" file.any | xxd -dostat -c "%s" file.any | xxd -
file_size_kb=`du -k "$filename" | cut -f1`
Problem z używaniem statpolega na tym, że jest to rozszerzenie GNU (Linux). du -ki cut -f1są określone przez POSIX, a zatem są przenośne dla dowolnego systemu Unix.
Na przykład Solaris jest dostarczany z bash, ale nie z stat. Nie jest to więc całkowicie hipotetyczne.
lsma podobny problem, ponieważ nie określono dokładnego formatu danych wyjściowych, dlatego parsowanie danych wyjściowych nie jest możliwe przenośne. du -hjest także rozszerzeniem GNU.
Trzymaj się przenośnych konstrukcji tam, gdzie to możliwe, a ułatwisz komuś życie w przyszłości. Może twój własny.
dunie podaje rozmiaru pliku, lecz wskazuje nieco ilość miejsca, które zajmuje plik, który jest nieznacznie inny (zwykle rozmiar zgłaszany przez duto rozmiar pliku zaokrąglony w górę do najbliższej liczby bloków, gdzie blok jest zwykle 512B lub 1kB lub 4kB).
--byteslub -bzamiast -k, powinno być przyjętą odpowiedzią.
-h(„ludzka”)du daje najbardziej odpowiednią odpowiedź dla ogólnych przypadków: file_size=`du -h "$filename" | cut -f1ponieważ wyświetli odpowiednio K (kilobajty), M (megabajty) lub G (gigabajty).
-hjest rozszerzeniem GNU; to nie jest standardowe
Możesz także użyć polecenia „liczba słów” ( wc):
wc -c "$filename" | awk '{print $1}'
Problem wcpolega na tym, że dodaje nazwę pliku i wcina dane wyjściowe. Na przykład:
$ wc -c somefile.txt
1160 somefile.txt
Jeśli chcesz uniknąć tworzenia łańcuchów tłumaczonych w pełnym języku lub edytora strumieniowego, aby uzyskać liczbę plików, po prostu przekieruj dane wejściowe z pliku, aby wcnigdy nie widział nazwy pliku:
wc -c < "$filename"
Ta ostatnia forma może być używana z zastępowaniem poleceń, aby łatwo pobrać wartość, której szukałeś jako zmienną powłoki, jak wspomniano poniżej Gilles .
size="$(wc -c <"$filename")"
wc -c <"$FILENAME"daje więc rozmiar bez żadnych innych cruft size=$(wc -c <"$FILENAME").
wc -c < filewydaje się być bardzo szybki, przynajmniej na OS X. Zgaduję, że wc ma mózg, aby spróbować statycznie zapisać plik, jeśli podano tylko -c.
wc -cużywa fstat, ale następnie szuka drugiego bloku pliku i odczytuje ostatnie st_blksizebajty. Najwyraźniej dzieje się tak, ponieważ pliki w Linuksie /proci /sysna przykład mają rozmiary statystyk, które są jedynie przybliżone , i wcchcą zgłosić rzeczywisty rozmiar, a nie rozmiar podany w statystykach. Zgaduję, że wc -czgłaszanie innego rozmiaru byłoby dziwniejsze wc, ale nie jest pomysłem odczytywanie danych z pliku, jeśli jest to zwykły plik na dysku i nie ma go w pamięci. Albo gorzej, przechowywanie na taśmie w pobliżu linii ...
printfnadal widzi wcięcie, np. printf "Size: $size"-> size: <4 spaces> 54339. Z drugiej strony echoignoruje białe znaki. W jakikolwiek sposób, aby był spójny?
fstat. Spróbuj uruchomić, strace wc -c </etc/passwda zobaczysz, co robi.
BSD (Mac OS X) statma inną flagę argumentów formatu i różne specyfikatory pól. Od man stat(1):
-f format: Wyświetlanie informacji przy użyciu określonego formatu. Zobacz poprawne formaty w sekcji FORMATY.z: Rozmiar pliku w bajtach.Więc teraz wszyscy razem:
stat -f%z myfile1.txt
Zależy, co rozumiesz przez rozmiar .
size=$(wc -c < "$file")
poda liczbę bajtów, które można odczytać z pliku. IOW, jest to rozmiar zawartości pliku. Odczyta jednak zawartość pliku (z wyjątkiem sytuacji, gdy plik jest zwykłym plikiem lub dowiązaniem symbolicznym do zwykłego pliku w większości wcimplementacji jako optymalizacja). To może mieć skutki uboczne. Na przykład dla nazwanego potoku to, co zostało przeczytane, nie może być ponownie odczytane, a dla rzeczy takich jak /dev/zerolub /dev/randomo nieskończonej wielkości zajmie to trochę czasu. Oznacza to również, że potrzebujesz readuprawnień do pliku, a znacznik czasu ostatniego dostępu do pliku może zostać zaktualizowany.
Jest to standardowe i przenośne, jednak należy pamiętać, że niektóre wcimplementacje mogą zawierać wiodące spacje na tym wyjściu. Jednym ze sposobów na pozbycie się ich jest użycie:
size=$(($(wc -c < "$file")))
lub aby uniknąć błędu związanego z pustym wyrażeniem arytmetycznym w dashlub yashgdy wcnie generuje danych wyjściowych (np. gdy nie można otworzyć pliku):
size=$(($(wc -c < "$file") +0))
ksh93ma wcwbudowaną funkcję (pod warunkiem, że ją włączysz, możesz ją również wywołać jako command /opt/ast/bin/wc), co czyni ją najbardziej wydajną dla zwykłych plików w tej powłoce.
Różne systemy mają wywołane polecenie, statktóre jest interfejsem do wywołań systemowych stat()lub lstat().
Raportują informacje znalezione w i-węźle. Jedną z tych informacji jest st_sizeatrybut. W przypadku zwykłych plików jest to rozmiar zawartości (ile danych można odczytać z niej przy braku błędu (tego większość wc -cimplementacji używa do optymalizacji). W przypadku dowiązań symbolicznych jest to rozmiar w bajtach ścieżki docelowej. W przypadku nazwanych potoków, w zależności od systemu, jest to 0 lub liczba bajtów aktualnie w buforze potoków. To samo dotyczy urządzeń blokowych, gdzie w zależności od systemu otrzymujesz 0 lub rozmiar w bajtach pamięci podstawowej.
Nie potrzebujesz uprawnień do odczytu pliku, aby uzyskać te informacje, tylko uprawnienia do wyszukiwania w katalogu, do którego jest on podłączony.
W porządku chronologicznym istnieje:
IRIXstat (lata 90-te):
stat -qLs -- "$file"
zwraca st_sizeatrybut $file( lstat()) lub:
stat -s -- "$file"
to samo, z wyjątkiem sytuacji, gdy $filejest dowiązaniem symbolicznym, w którym to przypadku jest to st_sizeplik po rozdzieleniu dowiązania symbolicznego.
zsh statwbudowany (obecnie znany również jako zstat) w zsh/statmodule (załadowany zmodload zsh/stat) (1997):
stat -L +size -- $file # st_size of file
stat +size -- $file # after symlink resolution
lub do przechowywania w zmiennej:
stat -L -A size +size -- $file
oczywiście jest to najbardziej wydajny w tej powłoce.
GNUstat (2001); także w BusyBox statod 2005 roku (skopiowane z GNU stat):
stat -c %s -- "$file" # st_size of file
stat -Lc %s -- "$file" # after symlink resolution
(zauważ, że znaczenie -Ljest odwrócone w porównaniu do IRIX lub zsh stat.
BSDstat (2002):
stat -f %z -- "$file" # st_size of file
stat -Lf %z -- "$file" # after symlink resolutionLub możesz użyć funkcji stat()/ lstat()jakiegoś języka skryptowego, takiego jak perl:
perl -le 'print((lstat shift)[7])' -- "$file"
System AIX zawiera również istatpolecenie, które zrzuci wszystkie informacje stat()(nie lstat(), więc nie będzie działać na dowiązaniach symbolicznych) i które można przetworzyć później , na przykład:
LC_ALL=C istat "$file" | awk 'NR == 4 {print $5}'
(dzięki @JeffSchaller za pomoc w ustaleniu szczegółów ).
W tcsh:
@ size = -Z $file:q
(rozmiar po rozdzielczości dowiązania symbolicznego)
Na długo przed wprowadzeniem statpolecenia GNU to samo można osiągnąć dzięki findpoleceniu GNU z jego -printfpredykatem (już w 1991 r.):
find -- "$file" -prune -printf '%s\n' # st_size of file
find -L -- "$file" -prune -printf '%s\n' # after symlink resolution
Jednym z problemów jest jednak, że nie działa, jeśli $filerozpoczyna się -lub jest findorzeczenie (jak !, (...).
Standardowe polecenie, aby uzyskać informacje stat()/, lstat()to ls.
POSIXly możesz:
LC_ALL=C ls -dn -- "$file" | awk '{print $5; exit}'
i dodaj -Lto samo po rozwiązaniu dowiązania symbolicznego. To nie działa w przypadku plików urządzeń, gdzie 5- tym polem jest numer główny urządzenia zamiast jego rozmiaru.
W przypadku urządzeń blokowych systemy, w których stat()zwraca 0 st_size, zwykle mają inne interfejsy API do zgłaszania wielkości urządzenia blokowego. Na przykład Linux ma BLKGETSIZE64 ioctl()i większość dystrybucji Linuksa jest teraz dostarczana z blockdevpoleceniem, które może z niego skorzystać:
blockdev --getsize64 -- "$device_file"
W tym celu potrzebujesz jednak uprawnienia do odczytu pliku urządzenia. Zwykle można uzyskać rozmiar w inny sposób. Na przykład (wciąż w systemie Linux):
lsblk -bdno size -- "$device_file"
Powinien działać, z wyjątkiem pustych urządzeń.
Podejście, które działa dla wszystkich widocznych plików (a więc obejmuje zwykłe pliki, większość urządzeń blokowych i niektóre urządzenia znakowe), polega na otwarciu pliku i szukaniu do końca:
Z zsh(po załadowaniu zsh/systemmodułu):
{sysseek -w end 0 && size=$((systell(0)))} < $fileZ ksh93:
< "$file" <#((size=EOF))
lub
{ size=$(<#((EOF))); } < "$file"z perl:
perl -le 'seek STDIN, 0, 2 or die "seek: $!"; print tell STDIN' < "$file"Dla nazwanych potoków, widzieliśmy, że niektóre systemy (AIX, Solaris, HP / UX przynajmniej) sprawiają, że ilość danych w buforze rur dostępnych w stat()„s st_size. Niektóre (jak Linux lub FreeBSD) nie.
Przynajmniej w systemie Linux możesz użyć następującego FIONREAD ioctl()po otwarciu potoku (w trybie odczytu + zapisu, aby go nie zawiesić):
fuser -s -- "$fifo_file" &&
perl -le 'require "sys/ioctl.ph";
ioctl(STDIN, &FIONREAD, $n) or die$!;
print unpack "L", $n' <> "$fifo_file"
Należy jednak pamiętać, że chociaż nie odczytuje zawartości potoku, samo otwarcie nazwanej potoku tutaj może nadal mieć skutki uboczne. Używamy fusernajpierw do sprawdzenia, czy jakiś proces ma już otwartą rurkę, aby to złagodzić, ale nie jest to niezawodne, ponieważ fusermoże nie być w stanie sprawdzić wszystkich procesów.
Do tej pory rozważaliśmy jedynie rozmiar podstawowych danych powiązanych z plikami. To nie bierze pod uwagę rozmiaru metadanych i całej infrastruktury pomocniczej potrzebnej do przechowywania tego pliku.
Kolejnym atrybutem i-węzła zwróconym przez stat()jest st_blocks. Jest to liczba 512-bajtowych bloków używanych do przechowywania danych pliku (a czasem niektórych jego metadanych, takich jak rozszerzone atrybuty w systemach plików ext4 w systemie Linux). Nie obejmuje to samego i-węzła ani wpisów w katalogach, z którymi plik jest powiązany.
Rozmiar i użycie dysku niekoniecznie są ściśle związane z kompresją, rzadkością (czasami niektóre metadane), dodatkowa infrastruktura, taka jak bloki pośrednie w niektórych systemach plików, ma na to wpływ.
Tego zwykle duużywa się do zgłaszania użycia dysku. Większość wyżej wymienionych poleceń będzie w stanie uzyskać te informacje.
POSIXLY_CORRECT=1 ls -sd -- "$file" | awk '{print $1; exit}'POSIXLY_CORRECT=1 du -s -- "$file" (nie dotyczy katalogów, w których obejmowałoby to użycie plików na dysku).find -- "$file" -printf '%b\n'zstat -L +block -- $filestat -c %b -- "$file"stat -f %b -- "$file"perl -le 'print((lstat shift)[12])' -- "$file"wc -cużywa fstat, ale potem odczytuje ostatnie st_blksizebajty. Najwyraźniej dzieje się tak, ponieważ pliki w Linuksie /proci /sysna przykład mają rozmiary statystyk, które są jedynie przybliżone . Jest to dobre dla poprawności, ale złe, jeśli koniec pliku znajduje się na dysku, a nie w pamięci (szczególnie jeśli jest używany na wielu plikach w pętli). I bardzo źle, jeśli plik jest migrowany do pamięci taśmowej nearline lub np. Systemu plików FUSE z przezroczystą dekompresją.
ls -go file | awk '{print $3}'
-gobyłyby to SysV, nie działałyby na BSD (opcjonalnie (XSI) w POSIX). Potrzebujesz również ls -god file | awk '{print $3; exit}'( -daby działał na katalogach, exitdla dowiązań symbolicznych z nowymi liniami w celu). Pozostają również problemy z plikami urządzeń.
wc -cktóra podaje liczbę bajtów.
Ten skrypt łączy wiele sposobów obliczania rozmiaru pliku:
(
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}'
Skrypt działa na wielu systemach uniksowych, w tym Linux, BSD, OSX, Solaris, SunOS itp.
Rozmiar pliku pokazuje liczbę bajtów. Jest to rozmiar pozorny, który jest bajtami używanymi przez plik na typowym dysku, bez specjalnej kompresji, specjalnych rzadkich obszarów lub nieprzydzielonych bloków itp.
Ten skrypt ma wersję produkcyjną z dodatkową pomocą i więcej opcji tutaj: https://github.com/SixArm/file-size
stat wydaje się to robić przy najmniejszej liczbie wywołań systemowych:
$ 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
ls -l filename poda wiele informacji o pliku, w tym jego rozmiar, uprawnienia i właściciela.
Rozmiar pliku w piątej kolumnie i jest wyświetlany w bajtach. W poniższym przykładzie rozmiar pliku wynosi nieco poniżej 2 KB:
-rw-r--r-- 1 user owner 1985 2011-07-12 16:48 index.php
Edycja: najwyraźniej nie jest tak niezawodny jak statpolecenie.
ls -li statpolecenie podają wiarygodne informacje o rozmiarze. Nie znalazłem żadnego odniesienia do czegoś przeciwnego. ls -sda rozmiar w liczbie bloków.
du filename poinformuje cię o zużyciu dysku w bajtach.
Wolę du -h filename, co daje rozmiar w formacie czytelnym dla człowieka.
duwydruku wielkości w blokach 1024 bajtów, a nie zwykła liczba bajtów.
dudaje wyjście w liczbie 512-bajtowych jednostek. GNU duużywa zamiast tego kibibajtów, chyba że jest wywoływane POSIXLY_CORRECTw jego środowisku.
Twórz małe funkcje narzędziowe w swoich skryptach powłoki, które możesz delegować.
Przykład
#! /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 podstawie informacji uzyskanych z odpowiedzi @ Stéphane Chazelas.
gzip -v < file > /dev/nullaby sprawdzić kompresję pliku.
caseoświadczenia. casejest konstrukcją Bourne / POSIX, która wykonuje dopasowanie wzorca. [[...]]jest tylko ksh / bash / zsh (z odmianami).
Znalazłem wkładkę AWK 1 i miał błąd, ale go naprawiłem. Dodałem także w 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] }')
Biorąc pod uwagę, że statystyki nie są dostępne w każdym systemie, prawie zawsze można użyć rozwiązania AWK. Przykład; Raspberry Pi nie ma statystyk, ale ma awk .
Jeden inny sposób zgodny z POSIX byłoby użyć awkz jego length()funkcji, która zwraca długość, w znakach na każdej linii pliku wejściowego, z wyjątkiem nowej linii znaków. Tak robiąc
awk '{ sum+=length } END { print sum+NR }' file
zapewniamy, że NRjest dodawany do sum, dzięki czemu łączna liczba znaków i całkowita liczba nowych linii napotkanych w pliku. length()Funkcja w awkprzyjmuje argument, który domyślnie środek length($0), który jest dla bieżącego całej linii.
printf 'a\nb' | awk '{ sum+=length } END { print sum+NR }'powinien wypisać 3, ale wypisuje 4.
Sam lubię opcję wc. W połączeniu z „bc” możesz uzyskiwać liczby dziesiętne w dowolnej liczbie miejsc.
Szukałem ulepszenia skryptu, który wybudził kolumnę „rozmiar pliku” polecenia „ls -alh”. Nie chciałem tylko liczb całkowitych, a dwa miejsca po przecinku wydawały się pasować, więc po przeczytaniu tej dyskusji wymyśliłem poniższy kod.
Sugeruję przerwanie linii w średnikach, jeśli umieścisz to w skrypcie.
file=$1; string=$(wc -c $file); bite=${string% *}; okay=$(echo "scale=2; $bite/1024" | bc);friend=$(echo -e "$file $okay" "kb"); echo -e "$friend"
Mój skrypt nazywa się gpfl , ponieważ „pobierz długość pliku obrazu”. Używam go po zrobieniu zdjęcia pliku w imagemagick, przed otwarciem lub ponownym załadowaniem obrazu w przeglądarce jpeg z GUI.
Nie wiem, jak to ocenia się jako „odpowiedź”, ponieważ wiele zapożycza z tego, co zostało już zaoferowane i omówione. Więc zostawię to tam.
BZT
wcczyta ostatni blok pliku, na wypadek gdyby stat.st_sizebyło to tylko przybliżenie (jak w przypadku Linuksa /proci /sysplików). Myślę, że nie zdecydował się na głównym komentarz bardziej skomplikowana, gdy dodał, że logika paru linie w dół: lingrok.org/xref/coreutils/src/wc.c#246
Najszybsza i najprostsza metoda (IMO) to:
bash_var=$(stat -c %s /path/to/filename)
dui wcodpowiedzi, które powinny zawierać zastrzeżenie, NIGDY NIE RÓŻ TEGO W ŻYCIU. Właśnie użyłem swojej odpowiedzi w dzisiejszej aplikacji z życia i pomyślałem, że warto się nią podzielić. Chyba wszyscy mamy swoje opinie wzruszają ramionami .