Moje obecne rozwiązanie byłoby takie find <expr> -exec printf '.' \; | wc -c
, ale trwa to zbyt długo, gdy wyników jest ponad 10000. Czy nie ma szybszego / lepszego sposobu na zrobienie tego?
Odpowiedzi:
Spróbuj tego zamiast (wymaga find
„s -printf
wsparcia):
find <expr> -type f -printf '.' | wc -c
Będzie to bardziej niezawodne i szybsze niż liczenie linii.
Zwróć uwagę, że używam polecenia find
, a printf
nie polecenia zewnętrznego.
Ławmy trochę:
$ ls -1
a
e
l
ll.sh
r
t
y
z
Test porównawczy mojego fragmentu:
$ time find -type f -printf '.' | wc -c
8
real 0m0.004s
user 0m0.000s
sys 0m0.007s
Z pełnymi liniami:
$ time find -type f | wc -l
8
real 0m0.006s
user 0m0.003s
sys 0m0.000s
Więc moje rozwiązanie jest szybsze =) (ważną częścią jest real
linia)
-printf '.'
Dlaczego nie
find <expr> | wc -l
jako proste rozwiązanie przenośne? Twoje oryginalne rozwiązanie tworzy nowy proces printf
dla każdego znalezionego pliku i jest to bardzo kosztowne (jak właśnie znalazłeś).
Zauważ, że liczba ta przekroczy, jeśli masz nazwy plików z osadzonymi znakami nowego wiersza, ale jeśli je masz, to podejrzewam, że Twoje problemy są nieco głębsze.
To rozwiązanie jest z pewnością wolniejsze niż niektóre inne find -> wc
rozwiązania tutaj, ale jeśli byłeś skłonny zrobić coś innego z nazwami plików oprócz ich zliczania, możesz read
z find
wyniku.
n=0
while read -r -d ''; do
((n++)) # count
# maybe perform another act on file
done < <(find <expr> -print0)
echo $n
Jest to po prostu modyfikacja rozwiązania znalezionego w BashGuide, które poprawnie obsługuje pliki o niestandardowych nazwach, ustawiając find
separator wyjściowy bajtem NUL, używając print0
i odczytując z niego ''
(bajt NUL) jako ogranicznik pętli.
To jest moja countfiles
funkcja w moim ~/.bashrc
(jest dość szybka, powinna działać dla Linuksa i FreeBSD find
i nie daje się zwieść ścieżkom plików zawierających znaki nowej linii; ostatnia wc
liczy tylko NUL bajtów):
countfiles ()
{
command find "${1:-.}" -type f -name "${2:-*}" -print0 |
command tr -dc '\0' | command wc -c;
return 0
}
countfiles
countfiles ~ '*.txt'