Na Linuksie używam stat --format="%s" FILE
, ale Solaris, do którego mam dostęp, nie ma polecenia stat. Czego więc powinienem użyć?
Piszę skrypty Bash i tak naprawdę nie mogę zainstalować żadnego nowego oprogramowania w systemie.
Rozważałem już użycie:
perl -e '@x=stat(shift);print $x[7]' FILE
lub nawet:
ls -nl FILE | awk '{print $5}'
Ale żadne z tych nie wygląda rozsądnie - uruchomienie Perla tylko po to, aby uzyskać rozmiar pliku? Lub uruchamiasz 2 polecenia, aby zrobić to samo?
Odpowiedzi:
wc -c < filename
(skrót od liczby słów,-c
wyświetla liczbę bajtów) jest przenośnym rozwiązaniem POSIX . Tylko format wyjściowy może nie być jednolity na różnych platformach, ponieważ niektóre spacje mogą być dołączane na początku (tak jest w przypadku Solaris).Nie pomijaj przekierowania danych wejściowych. Gdy plik jest przekazywany jako argument, nazwa pliku jest wypisywana po liczbie bajtów.
Martwiłem się, że to nie zadziała dla plików binarnych, ale działa dobrze zarówno na Linuksie, jak i na Solarisie. Możesz to wypróbować
wc -c < /usr/bin/wc
. Co więcej, narzędzia POSIX gwarantują obsługę plików binarnych , chyba że wyraźnie określono inaczej.źródło
wc -c < file
jeśli nie chcesz, aby nazwa pliku się pojawiała.wc
w potoku musiread()
cały strumień policzyć bajty. Rozwiązanials
/awk
(i podobne) używają wywołania systemowego, aby uzyskać rozmiar, który powinien być czasem liniowym (w porównaniu do O (rozmiar))wc
że byłem bardzo powolny, kiedy ostatnio robiłem to na pełnym dysku twardym. Był na tyle wolny, że mogłem ponownie napisać scenariusz, zanim skończyłem pierwszy, przyszedłem tutaj, aby przypomnieć sobie, jak to zrobiłem lol.wc -c
; wygląda o wiele schludniej, alels
+awk
jest lepsze pod względem szybkości / wykorzystania zasobów. Chciałem też tylko zwrócić uwagę, że w rzeczywistości musisz przetworzyć wynikiwc
również w programie, ponieważ w niektórych systemach będzie on zawierał spacje przed wynikiem, które możesz potrzebować usunąć przed wykonaniem porównań.wc -c
jest świetny, ale nie zadziała, jeśli nie masz uprawnień do odczytu pliku.Skończyło się na napisaniu własnego programu (naprawdę małego), który wyświetlał tylko rozmiar. Więcej informacji tutaj: http://fwhacking.blogspot.com/2011/03/bfsize-print-file-size-in-bytes-and.html
Moim zdaniem dwa najbardziej czyste sposoby korzystania z typowych narzędzi Linuksa to:
Ale ja po prostu nie chcę wpisywać parametrów ani potokować wyjścia tylko po to, aby uzyskać rozmiar pliku, więc używam własnego rozmiaru bfsize.
źródło
stat
jest dla nich opcją.wc -c
plik 10 MB zajmuje 4090 ms w porównaniu z „0” msstat -c %s
, więc zgadzam się, że warto mieć alternatywne rozwiązania, nawet jeśli nie odpowiadają one dokładnie na zadane pytanie.stat -c %s /usr/bin/stat
stat: illegal option -- c
usage: stat [-FlLnqrsx] [-f format] [-t timefmt] [file ...]
Mimo że
du
zwykle wyświetla użycie dysku, a nie rzeczywisty rozmiar danych, GNU coreutilsdu
może wypisać „pozorny rozmiar” pliku w bajtach:Ale to nie będzie działać pod BSD, Solaris, macOS, ...
źródło
brew install coreutils
igdu -b
osiągnie ten sam efektwc
trzeba przeczytać cały plik, zanim da wynik,du
jest natychmiastowy.du -b
w zupełnie innym kontekście wdu
uzasadnieniu .lstat
wywołania, więc jego wydajność nie zależy od rozmiaru pliku. Krótszy niżstat -c '%s'
, ale mniej intuicyjny i działa inaczej dla folderów (drukuje rozmiar każdego pliku w środku).du
może zbliżyć się za pomocądu -A -B1
, ale nadal wyświetla wynik jako wielokrotność bloków 1024B. Nie udało się go zmusić do wydrukowania liczby bajtów. Nawet ustawienieBLOCKSIZE=1
w środowisku nie pomaga, ponieważ używa się wtedy bloku 512B.W końcu zdecydowałem się użyć ls i rozszerzenia tablicy bash:
to nie jest zbyt ładne, ale przynajmniej robi tylko 1 fork + execve i nie opiera się na dodatkowym języku programowania (perl / ruby / python / cokolwiek)
źródło
ls -ln FILE | { read _ _ _ _ size _ && echo "$size"; }
nie potrzebuje rozwidlać w drugim etapie potoku, ponieważ używa tylko wbudowanych, ale Bash 4.2.37 na forkach Linuksa dwukrotnie (execve
choć wciąż tylko jeden ).read _ _ _ _ size _ <<<"$(exec ls -ln /usr/bin/wc)" && echo "$size"
działa z pojedynczym rozwidleniem i pojedynczym wykonaniem, ale używa pliku tymczasowego jako ciągu tutaj. Można go uczynić przenośnym, zastępując ciąg znaków tutaj dokumentem tutaj zgodnym z POSX . BTW zwróć uwagęexec
na podpowłokę. Bez tego Bash wykonuje jeden fork dla podpowłoki i drugi dla polecenia działającego wewnątrz. Tak jest w przypadku kodu, który podajesz w tej odpowiedzi. też.-l
Jest zbędny w obecności-n
. Cytowanie POSIXls
manpage :-n
: Włącz-l
(ell) opcja, ale pisząc właściciela pliku lub grupy, pisać UID numeryczna pliku lub GID zamiast nazwy użytkownika lub grupy, odpowiednio. Wyłącz-C
,-m
oraz-x
opcje.Najszybsze rozwiązanie dla wielu platform (używa tylko pojedynczego fork () dla ls , nie próbuje zliczać rzeczywistych znaków, nie tworzy niepotrzebnych awk, perl itp.).
Testowane na MacOS, Linux - może wymagać niewielkich modyfikacji dla Solaris:
W razie potrzeby uprość argumenty ls i dostosuj przesunięcie w $ {__ ln [3]}.
Uwaga: nastąpi podążanie za dowiązaniami symbolicznymi.
źródło
BSD mają
stat
inne opcje niż te z GNU coreutils, ale podobne możliwości.Działa to na macOS (testowane 10.12), FreeBSD , NetBSD i OpenBSD .
źródło
stat
użyteczności.Podczas przetwarzania danych
ls -n
wyjściowych, jako alternatywa dla źle przenośnych tablic powłoki, można użyć argumentów pozycyjnych, które tworzą jedyną tablicę i są jedynymi zmiennymi lokalnymi w standardowej powłoce. Zawiń nadpisanie argumentów pozycyjnych w funkcji, aby zachować oryginalne argumenty w swoim skrypcie lub funkcji.Spowoduje to podzielenie wyniku programu
ln -dn
zgodnie z bieżącymiIFS
ustawieniami zmiennych środowiskowych, przypisanie go do argumentów pozycyjnych i powtórzenie piątego. W-d
gwarantuje katalogi są właściwie traktowane i-n
zapewnia, że nazwy użytkowników i grupy nie muszą być rozwiązane, w przeciwieństwie do-l
. Ponadto nazwy użytkowników i grup zawierające białe znaki mogą teoretycznie złamać oczekiwaną strukturę linii; są one zwykle niedozwolone, ale taka możliwość wciąż sprawia, że programista zatrzymuje się i myśli.źródło
Jeśli używasz
find
plików z GNU fileutils:Niestety, inne implementacje
find
zwykle nie obsługują-maxdepth
, ani-printf
. Tak jest w przypadku np. Solaris i macOSfind
.źródło
size=$(test -f filename && find filename -printf '%s')
.-maxdepth
ma na celu zapobieganiefind
rekurencyjności (ponieważ operacja,stat
która musi zostać zastąpiona, nie jest). W Twoimfind
poleceniu brakuje a,-name
atest
polecenie nie jest konieczne.find
przeszukuje swoje parametry rekurencyjnie w poszukiwaniu plików spełniających podane kryteria. Jeśli parametry nie są katalogami, rekurencja jest… dość prosta. Dlatego najpierw testuję,filename
czy naprawdę jest to zwykły plik, a następnie drukuję jego rozmiar, używającfind
tego, który nie ma gdzie się powtarzać.find . -maxdepth 1 -type f -name filename -printf '%s'
działa tylko wtedy, gdy plik znajduje się w bieżącym katalogu i może nadal badać każdy plik w katalogu, co może być powolne. Lepsze wykorzystanie (jeszcze krótsze!)find filename -maxdepth 1 -type f -printf '%s'
.Możesz użyć
find
polecenia, aby pobrać zestaw plików (tutaj pliki tymczasowe są rozpakowywane). Następnie możesz użyćdu
polecenia, aby uzyskać rozmiar każdego pliku w postaci czytelnej dla człowieka za pomocą-h
przełącznika.WYNIK:
źródło
Twój pierwszy przykład w Perlu nie wydaje mi się nierozsądny.
Z takich powodów przeszedłem od pisania skryptów powłoki (w bash / sh itp.) Do pisania wszystkich, oprócz najbardziej trywialnych skryptów w Perlu. Odkryłem, że muszę uruchamiać Perla dla określonych wymagań, a gdy robiłem to coraz częściej, zdałem sobie sprawę, że pisanie skryptów w Perlu jest prawdopodobnie bardziej wydajne (pod względem języka i szerokiej gamy bibliotek dostępnych przez CPAN ) i skuteczniejszy sposób na osiągnięcie tego, co chciałem.
Zauważ, że inne języki skryptowe powłoki (np. Python / ruby) bez wątpienia będą miały podobne udogodnienia i możesz chcieć je wypróbować do swoich celów. Omawiam Perla tylko dlatego, że jest to język, którego używam i który znam.
źródło
jeśli masz Perla w swoim Solarisie, użyj go. W przeciwnym razie ls z awk jest następnym najlepszym rozwiązaniem, ponieważ nie masz statystyk lub twoje znalezisko nie jest znalezieniem GNU.
źródło
W Solarisie jest sztuczka, której użyłem, jeśli poprosisz o rozmiar więcej niż jednego pliku, zwraca tylko całkowity rozmiar bez nazw - więc dołącz pusty plik, taki jak / dev / null jako drugi plik:
np. plik poleceń, którego chcesz / dev / null
Nie pamiętam, które polecenie rozmiaru działa dla ls / wc / etc - niestety nie mam skrzynki solaris, aby to przetestować.
źródło
na Linuksie, którego możesz użyć
du -h $FILE
, czy to działa również na Solaris?źródło
Czy próbowałeś du -ks | awk '{print $ 1 * 1024}'. To może po prostu zadziałać.
źródło