@ haunted85 statjest najprostszym sposobem, zakładając, że używasz Linuksa lub Cygwina ( statnie jest standardem). wc -cjak sugeruje Eugéne, jest przenośny.
Gilles
2
stat: illegal option -- c
Iulian Onofrei
stat --printf="%s" file.txtnie
wypisuje
5
W systemie MacOS działa to:stat -f%z myfile.tar
ccpizza
2
@woohoo Twój monit zastępuje dane wyjściowe. 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 -
wnuka
92
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).
Gilles
7
@Gilles, rzadkie pliki (tj. Te z dziurami) zgłaszają mniej niż długość.
vonbrand,
5
To, z --byteslub -bzamiast -k, powinno być przyjętą odpowiedzią.
Amedee Van Gasse
1
Opcja -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).
fralau
1
@fralau: OP chce „przypisać to do zmiennej bash, aby móc jej później użyć”, więc jest znacznie bardziej prawdopodobne, że chcą rzeczywistej wartości liczbowej, a nie przybliżenia czytelnego dla człowieka. Ponadto -hjest rozszerzeniem GNU; to nie jest standardowe
Nemo
73
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 .
wc -c <"$FILENAME"daje więc rozmiar bez żadnych innych cruft size=$(wc -c <"$FILENAME").
Gilles
6
Jeszcze tylko jedna kwestia: Właśnie go przetestowałem i 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.
Edward Falk,
4
@EdwardFalk: GNU 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 ...
Peter Cordes,
1
Wygląda na to, że 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?
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.
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.
zshstatwbudowany (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 zshstat.
stat -f %z --"$file"# st_size of file
stat -Lf%z --"$file"# after symlink resolution
Lub 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:
(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 BLKGETSIZE64ioctl()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)))}< $file
Z 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 FIONREADioctl()po otwarciu potoku (w trybie odczytu + zapisu, aby go nie zawiesić):
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).
zdecydowanie najbardziej wyczerpująca i informacyjna odpowiedź. Dziękuję Ci. mogę to wykorzystać do tworzenia wieloplatformowych skryptów bashowych przy użyciu informacji o statystykach BSD i GNU
też by to nie zadziałałols -go file | awk '{print $3}'
Steven Penny
@StevenPenny -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ń.
Stéphane Chazelas
1
@ αғsнιη, Unix API nie rozróżnia plików tekstowych i binarnych. To wszystkie sekwencje bajtów. Niektóre aplikacje mogą chcieć interpretować te bajty jako tekst, ale oczywiście nie, wc -cktóra podaje liczbę bajtów.
Stéphane Chazelas
22
Ten skrypt łączy wiele sposobów obliczania rozmiaru pliku:
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.
Myślę, że zarówno polecenie , jak ls -li statpolecenie podają wiarygodne informacje o rozmiarze. Nie znalazłem żadnego odniesienia do czegoś przeciwnego. ls -sda rozmiar w liczbie bloków.
dabest1
2
@ dabest1 nie jest wiarygodny w tym sensie, że w innym Uniksie ich dane wyjściowe mogą być inne (aw niektórych Uniksach tak jest).
Eugene Bujak
Tak, IIRC, Solaris domyślnie nie wyświetlał nazwy grupy, co prowadzi do zmniejszenia liczby kolumn w danych wyjściowych.
Edward Falk,
Ponieważ rozmiar jest czysto numeryczny, otoczony białymi spacjami, a rok daty jest czysto numeryczny, w zdefiniowanym formacie, możliwe byłoby użycie wyrażenia regularnego do traktowania użytkownika + właściciela jako jednego pola, niezależnie od tego, czy grupa była obecna. (ćwiczenie dla czytelnika!)
MikeW
5
du filename poinformuje cię o zużyciu dysku w bajtach.
Wolę du -h filename, co daje rozmiar w formacie czytelnym dla człowieka.
Ten smak duwydruku wielkości w blokach 1024 bajtów, a nie zwykła liczba bajtów.
Peter Lyons,
Zauważ, że standard dudaje wyjście w liczbie 512-bajtowych jednostek. GNU duużywa zamiast tego kibibajtów, chyba że jest wywoływane POSIXLY_CORRECTw jego środowisku.
Stéphane Chazelas
1
W przypadku plików typu katalog daje to miejsce na dysku dla katalogu, ale także dla wszystkich innych plików (rekurencyjnie).
Stéphane Chazelas
3
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.
@ StéphaneChazelas nie jestem pewien, czy uważam, że to poprawa. te stwierdzenia przypadków mogą łatwo zniechęcić noobów; Z pewnością nigdy nie pamiętam, jak je poprawnie :-) Czy instrukcje przypadków są z natury bardziej przenośne, odkąd to zrobiłeś? Rozumiem, że są więcej niż dwa przypadki, ale poza tym ... +
oligofren
1
Przypuszczam, że to także kwestia gustu, ale tutaj jest to typowy przypadek, w którym chciałbyś użyć caseoświadczenia. casejest konstrukcją Bourne / POSIX, która wykonuje dopasowanie wzorca. [[...]]jest tylko ksh / bash / zsh (z odmianami).
Stéphane Chazelas,
2
Znalazłem wkładkę AWK 1 i miał błąd, ale go naprawiłem. Dodałem także w PetaBytes po TeraBytes.
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 .
Zupełnie NIE to, o co poprosił PO, ale niezły kawałek pracy.
Gypsy Spellweaver
0
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.
Nie, jeśli ostatni wiersz nie kończy się na nowej linii: printf 'a\nb' | awk '{ sum+=length } END { print sum+NR }'powinien wypisać 3, ale wypisuje 4.
Izaak
-1
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.
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.
Wolałbym używać „stat” lub „ls”. Zazwyczaj nie lubię używać „wc”, aby uzyskać rozmiary plików, ponieważ fizycznie czyta cały plik. Jeśli masz dużo plików lub szczególnie dużych plików, może to zająć dużo czasu. Ale twoje rozwiązanie jest kreatywne ... + 1.
Kevin Fegan
2
Zgadzam się z pojęciem używania „stat” zamiast „wc” dla rozmiaru pliku, jednak jeśli użyjesz „wc -c”, żadne dane nie zostaną odczytane; zamiast tego lseek zostanie użyty do ustalenia liczby bajtów w pliku. lingrok.org/xref/coreutils/src/wc.c#228
bbaja42
1
@ bbaja42: zauważ, że GNU Coreutils 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
Następnie głosuj na jedną lub więcej istniejących odpowiedzi, które wspominają stat; nie trzeba go powtarzać ...
Jeff Schaller
1
@JeffSchaller Właśnie głosowałem odpowiedź Stephane'a na twoje instrukcje. Myślę, że jest to zbyt skomplikowane dla moich celów. Dlatego opublikowałem tę prostą odpowiedź dla podobnie myślących dusz.
WinEunuuchs2Unix
1
Dziękuję Ci; po prostu szósty przypadek odpowiedzi „stat” nie upraszcza tego pytania i odpowiedzi, ale wolałby, aby nowy czytelnik zadał sobie pytanie „czym różni się ta odpowiedź od pozostałych?” i prowadzą do większego zamieszania zamiast do mniej.
Jeff Schaller
@JeffSchaller Chyba. Ale mógłbym narzekać na wiele 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 .
pv
icat
dla polecenia kopiowania, które pokazuje postęp i ETA :)Odpowiedzi:
Twój najlepszy zakład, jeśli w systemie GNU:
Z statystyki człowieka :
W skrypcie bash:
UWAGA: patrz odpowiedź @ chbrown, aby dowiedzieć się, jak używać statystyki w terminalu w systemie Mac OS X.
źródło
stat
jest najprostszym sposobem, zakładając, że używasz Linuksa lub Cygwina (stat
nie jest standardem).wc -c
jak sugeruje Eugéne, jest przenośny.stat: illegal option -- c
stat --printf="%s" file.txt
niestat -f%z myfile.tar
man stat
mówi, że --printf pomija końcowy znak nowej linii. Użyj--format
lub,-c
aby zobaczyć wynik. Zyskaj więcej wglądu w porównaniustat --printf="%s" file.any | xxd -
dostat -c "%s" file.any | xxd -
Problem z używaniem
stat
polega na tym, że jest to rozszerzenie GNU (Linux).du -k
icut -f1
są 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.ls
ma podobny problem, ponieważ nie określono dokładnego formatu danych wyjściowych, dlatego parsowanie danych wyjściowych nie jest możliwe przenośne.du -h
jest 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.
źródło
du
nie podaje rozmiaru pliku, lecz wskazuje nieco ilość miejsca, które zajmuje plik, który jest nieznacznie inny (zwykle rozmiar zgłaszany przezdu
to rozmiar pliku zaokrąglony w górę do najbliższej liczby bloków, gdzie blok jest zwykle 512B lub 1kB lub 4kB).--bytes
lub-b
zamiast-k
, powinno być przyjętą odpowiedzią.-h
(„ludzka”)du
daje najbardziej odpowiednią odpowiedź dla ogólnych przypadków:file_size=`du -h "$filename" | cut -f1
ponieważ wyświetli odpowiednio K (kilobajty), M (megabajty) lub G (gigabajty).-h
jest rozszerzeniem GNU; to nie jest standardoweMożesz także użyć polecenia „liczba słów” (
wc
):Problem
wc
polega na tym, że dodaje nazwę pliku i wcina dane wyjściowe. Na przykład: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
wc
nigdy nie widział nazwy pliku: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 .
źródło
wc -c <"$FILENAME"
daje więc rozmiar bez żadnych innych cruftsize=$(wc -c <"$FILENAME")
.wc -c < file
wydaje 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 -c
używafstat
, ale następnie szuka drugiego bloku pliku i odczytuje ostatniest_blksize
bajty. Najwyraźniej dzieje się tak, ponieważ pliki w Linuksie/proc
i/sys
na przykład mają rozmiary statystyk, które są jedynie przybliżone , iwc
chcą zgłosić rzeczywisty rozmiar, a nie rozmiar podany w statystykach. Zgaduję, żewc -c
zgłaszanie innego rozmiaru byłoby dziwniejszewc
, 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 ...printf
nadal widzi wcięcie, np.printf "Size: $size"
->size: <4 spaces> 54339
. Z drugiej stronyecho
ignoruje białe znaki. W jakikolwiek sposób, aby był spójny?fstat
. Spróbuj uruchomić,strace wc -c </etc/passwd
a zobaczysz, co robi.BSD (Mac OS X)
stat
ma inną flagę argumentów formatu i różne specyfikatory pól. Odman 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:
źródło
Zależy, co rozumiesz przez rozmiar .
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
wc
implementacji 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/zero
lub/dev/random
o nieskończonej wielkości zajmie to trochę czasu. Oznacza to również, że potrzebujeszread
uprawnień 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
wc
implementacje mogą zawierać wiodące spacje na tym wyjściu. Jednym ze sposobów na pozbycie się ich jest użycie:lub aby uniknąć błędu związanego z pustym wyrażeniem arytmetycznym w
dash
lubyash
gdywc
nie generuje danych wyjściowych (np. gdy nie można otworzyć pliku):ksh93
mawc
wbudowaną funkcję (pod warunkiem, że ją włączysz, możesz ją również wywołać jakocommand /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,
stat
które jest interfejsem do wywołań systemowychstat()
lublstat()
.Raportują informacje znalezione w i-węźle. Jedną z tych informacji jest
st_size
atrybut. 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 -c
implementacji 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:
IRIX
stat
(lata 90-te):zwraca
st_size
atrybut$file
(lstat()
) lub:to samo, z wyjątkiem sytuacji, gdy
$file
jest dowiązaniem symbolicznym, w którym to przypadku jest tost_size
plik po rozdzieleniu dowiązania symbolicznego.zsh
stat
wbudowany (obecnie znany również jakozstat
) wzsh/stat
module (załadowanyzmodload zsh/stat
) (1997):lub do przechowywania w zmiennej:
oczywiście jest to najbardziej wydajny w tej powłoce.
GNU
stat
(2001); także w BusyBoxstat
od 2005 roku (skopiowane z GNUstat
):(zauważ, że znaczenie
-L
jest odwrócone w porównaniu do IRIX lubzsh
stat
.BSD
stat
(2002):Lub możesz użyć funkcji
stat()
/lstat()
jakiegoś języka skryptowego, takiego jakperl
:System AIX zawiera również
istat
polecenie, które zrzuci wszystkie informacjestat()
(nielstat()
, więc nie będzie działać na dowiązaniach symbolicznych) i które można przetworzyć później , na przykład:(dzięki @JeffSchaller za pomoc w ustaleniu szczegółów ).
W
tcsh
:(rozmiar po rozdzielczości dowiązania symbolicznego)
Na długo przed wprowadzeniem
stat
polecenia GNU to samo można osiągnąć dziękifind
poleceniu GNU z jego-printf
predykatem (już w 1991 r.):Jednym z problemów jest jednak, że nie działa, jeśli
$file
rozpoczyna się-
lub jestfind
orzeczenie (jak!
,(
...).Standardowe polecenie, aby uzyskać informacje
stat()
/,lstat()
tols
.POSIXly możesz:
i dodaj
-L
to 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 0st_size
, zwykle mają inne interfejsy API do zgłaszania wielkości urządzenia blokowego. Na przykład Linux maBLKGETSIZE64
ioctl()
i większość dystrybucji Linuksa jest teraz dostarczana zblockdev
poleceniem, które może z niego skorzystać: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):
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ładowaniuzsh/system
modułu):Z
ksh93
:lub
z
perl
: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()
„sst_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ć):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
fuser
najpierw do sprawdzenia, czy jakiś proces ma już otwartą rurkę, aby to złagodzić, ale nie jest to niezawodne, ponieważfuser
moż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()
jestst_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
du
uż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 -- $file
stat -c %b -- "$file"
stat -f %b -- "$file"
perl -le 'print((lstat shift)[12])' -- "$file"
źródło
wc -c
używafstat
, ale potem odczytuje ostatniest_blksize
bajty. Najwyraźniej dzieje się tak, ponieważ pliki w Linuksie/proc
i/sys
na 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}'
-go
byłyby to SysV, nie działałyby na BSD (opcjonalnie (XSI) w POSIX). Potrzebujesz równieżls -god file | awk '{print $3; exit}'
(-d
aby działał na katalogach,exit
dla dowiązań symbolicznych z nowymi liniami w celu). Pozostają również problemy z plikami urządzeń.wc -c
która podaje liczbę bajtów.Ten skrypt łączy wiele sposobów obliczania rozmiaru pliku:
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
źródło
stat wydaje się to robić przy najmniejszej liczbie wywołań systemowych:
źródło
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:
Edycja: najwyraźniej nie jest tak niezawodny jak
stat
polecenie.źródło
ls -l
istat
polecenie podają wiarygodne informacje o rozmiarze. Nie znalazłem żadnego odniesienia do czegoś przeciwnego.ls -s
da 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.źródło
stat -c "%s"
;)du
wydruku wielkości w blokach 1024 bajtów, a nie zwykła liczba bajtów.du
daje wyjście w liczbie 512-bajtowych jednostek. GNUdu
używa zamiast tego kibibajtów, chyba że jest wywoływanePOSIXLY_CORRECT
w jego środowisku.Twórz małe funkcje narzędziowe w swoich skryptach powłoki, które możesz delegować.
Przykład
Na podstawie informacji uzyskanych z odpowiedzi @ Stéphane Chazelas.
źródło
gzip -v < file > /dev/null
aby sprawdzić kompresję pliku.case
oświadczenia.case
jest 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.
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 .
źródło
Jeden inny sposób zgodny z POSIX byłoby użyć
awk
z jegolength()
funkcji, która zwraca długość, w znakach na każdej linii pliku wejściowego, z wyjątkiem nowej linii znaków. Tak robiączapewniamy, że
NR
jest dodawany dosum
, dzięki czemu łączna liczba znaków i całkowita liczba nowych linii napotkanych w pliku.length()
Funkcja wawk
przyjmuje argument, który domyślnie środeklength($0)
, który jest dla bieżącego całej linii.źródło
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
źródło
wc
czyta ostatni blok pliku, na wypadek gdybystat.st_size
było to tylko przybliżenie (jak w przypadku Linuksa/proc
i/sys
plikó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#246Najszybsza i najprostsza metoda (IMO) to:
źródło
du
iwc
odpowiedzi, 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 .