Мое текущее решение было бы таким find <expr> -exec printf '.' \; | wc -c
, но это занимает слишком много времени, когда есть более 10000 результатов. Нет ли более быстрого / лучшего способа сделать это?
Ответы:
Попробуйте вместо этого (требуется find
«s -printf
поддержка):
find <expr> -type f -printf '.' | wc -c
Это будет надежнее и быстрее, чем подсчет строк.
Обратите внимание, что я использую find
's printf
, а не внешнюю команду.
Давайте немного жмемся:
$ ls -1
a
e
l
ll.sh
r
t
y
z
Тест моего фрагмента:
$ time find -type f -printf '.' | wc -c
8
real 0m0.004s
user 0m0.000s
sys 0m0.007s
С полными строками:
$ time find -type f | wc -l
8
real 0m0.006s
user 0m0.003s
sys 0m0.000s
Так что мое решение быстрее =) (важная часть - real
линия)
-printf '.'
Почему нет
find <expr> | wc -l
как простое портативное решение? Ваше исходное решение порождает новый процесс printf
для каждого отдельного найденного файла, и это очень дорого (как вы только что обнаружили).
Обратите внимание, что это будет слишком большим, если у вас есть имена файлов со встроенными символами новой строки, но если они у вас есть, я подозреваю, что ваши проблемы немного глубже.
Это решение, безусловно, медленнее, чем некоторые другие find -> wc
решения здесь, но если вы были склонны сделать что-то еще с именами файлов в дополнение к их подсчету, вы могли бы сделать это read
из find
вывода.
n=0
while read -r -d ''; do
((n++)) # count
# maybe perform another act on file
done < <(find <expr> -print0)
echo $n
Это всего лишь модификация решения, найденного в BashGuide, которое должным образом обрабатывает файлы с нестандартными именами, делая find
выходной ограничитель нулевым байтом print0
и считывая его с использованием ''
(нулевой байт) в качестве разделителя цикла.
Это моя countfiles
функция в моем ~/.bashrc
(она достаточно быстрая, должна работать для Linux и FreeBSD find
, и ее не обманывают пути к файлам, содержащие символы новой строки; последний wc
просто считает байты NUL):
countfiles ()
{
command find "${1:-.}" -type f -name "${2:-*}" -print0 |
command tr -dc '\0' | command wc -c;
return 0
}
countfiles
countfiles ~ '*.txt'