bash - Как лучше всего посчитать результаты поиска?

Мое текущее решение было бы find <expr> -exec printf '.' \; | wc -c, но это занимает слишком много времени, когда имеется более 10000 результатов. Нет ли более быстрого /лучшего способа сделать это?

73 голоса | спросил David Stockinger 27 MarpmWed, 27 Mar 2013 20:07:58 +04002013-03-27T20:07:58+04:0008 2013, 20:07:58

5 ответов


0

Попробуйте вместо этого (требуется find в -printf поддержка):

find <expr> -type f -printf '.' | wc -c

Это будет более надежно и быстрее, чем подсчет строк.

Обратите внимание, что я использую find, а не внешняя команда.


Давайте немного поболтаем:

$ 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)

ответил Gilles Quenot 27 MarpmWed, 27 Mar 2013 20:14:23 +04002013-03-27T20:14:23+04:0008 2013, 20:14:23
0

Почему бы не

find <expr> | wc -l

как простое портативное решение? Ваше оригинальное решение порождает новый процесс printf для каждого найденного отдельного файла, и это очень дорого (как вы только что нашел)

Обратите внимание, что это приведет к пересчету, если у вас есть имена файлов со встроенными символами новой строки, но если у вас это есть, то я подозреваю, что ваши проблемы немного глубже: -)

ответил Brian Agnew 27 MarpmWed, 27 Mar 2013 20:10:39 +04002013-03-27T20:10:39+04:0008 2013, 20:10:39
0

Это моя 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'
ответил carlo 27 MarpmWed, 27 Mar 2013 21:04:19 +04002013-03-27T21:04:19+04:0009 2013, 21:04:19
0

Это решение, конечно, медленнее, чем некоторые другие решения 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 байтом NUL, используя print0 и чтение из него с использованием '' (байт NUL) в качестве разделителя цикла.

ответил John B 11 Jpm1000000pmSat, 11 Jan 2014 14:51:31 +040014 2014, 14:51:31
0

Мне нравится, когда я натыкаюсь на соревнование по скорости. Нет ничего плохого в использовании 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

Обратите внимание, что если вам необходимо учесть скрытые файлы, в вашем цикле for должно быть 2 аргумента: for devfile in /dev/.* /dev/*; do ... И это остается намного быстрее.

Счастливого взлома!

ответил user.friendly 31 Maypm16 2016, 18:36:04

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132