Мое текущее решение будет find <expr> -exec printf '.' \; | wc -c
, но это занимает слишком много времени, когда результатов более 10000. Нет ли более быстрого/лучшего способа сделать это?
Как лучше всего посчитать результаты поиска?
Ответ 1
Попробуйте это вместо (требуется find
-printf
поддержка):
find <expr> -type f -printf '.' | wc -c
Он будет более надежным и быстрее, чем подсчет строк.
Обратите внимание, что я использую find
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
)
Ответ 2
Почему бы не
find <expr> | wc -l
как простое переносное решение? Ваше исходное решение порождает новый процесс printf
для каждого найденного файла, и это очень дорого (как вы только что нашли).
Обратите внимание, что это будет превышать, если у вас есть имена файлов с встраиваемыми новыми строками, но если у вас есть это, то я подозреваю, что ваши проблемы немного глубже: -)
Ответ 3
Это решение, конечно, медленнее, чем некоторые другие решения 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
a NUL байта с использованием print0
и чтения из него с использованием ''
(NUL byte) в качестве разделителя циклов.
Ответ 4
Это моя функция 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'
Ответ 5
Мне нравится, когда я натыкаюсь на соревнование по скорости. Ничего плохого в использовании wc, но до тех пор, пока мы сравниваем - вот (я думаю) самое портативное и быстрое решение: ``
$ time (i=0; for d in /dev/sd*[a-z]; do ((i++)); done; echo $i)
25
real 0m0.001s
user 0m0.000s
sys 0m0.000s
По сравнению с использованием find/wc:
$ time find /dev/sd*[a-z] | wc -l
25
real 0m0.006s
user 0m0.000s
sys 0m0.004s
$ time find /dev/sd*[a-z] -printf . | wc -c
25
real 0m0.005s
user 0m0.000s
sys 0m0.000s
Обратите внимание, что если вам нужно учитывать скрытые файлы, вам нужно будет иметь 2 аргумента в вашем цикле for: for devfile in /dev/.* /dev/*; do ...
И он по-прежнему работает быстрее.
Счастливый взлом!