Який найкращий спосіб підрахувати результати "знайти"?


99

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


використовуйте wc -l для пошуку результатів
Мануель Сельва

Відповіді:


84

Спробуйте замість цього (потрібно find«s -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рядок)


6
Не еквівалентно, це надійніше =)
Gilles Quenot

6
Це не є більш надійним, якщо прапор -printf для пошуку не підтримується на вашій платформі. ;-)
Ренді Говард

7
Зверніть увагу, що ви можете збрити ще кілька наносекунд, не цитуючи крапку-printf '.'
Йенс,

6
@Jens - особливо, якщо взяти до уваги час, необхідний для набору тексту,
Брайан Егнью

6
При такому невеликому еталоні, у термінах, ймовірно, домінують інші фактори, ніж річ, яку ви хочете виміряти. Експеримент з великим деревом був би кориснішим. Але це отримує мій голос за те, що я фактично виконав те, про що просив ОП.
триплі

133

Чому ні

find <expr> | wc -l

як просте портативне рішення? Оригінальне рішення - це створення нового процесу printf для кожного знайденого окремого файлу, і це дуже дорого (як ви щойно знайшли).

Зауважте, що це перелічить, якщо у вас є вбудовані імена файлів із введеними новими рядками, але якщо у вас це є, то, підозрюю, ваші проблеми заглиблюються трохи глибше.


9
-1: перерви у файлі з новими рядками, і це повільніше, ніж підрахунок байтів =)
Жиль Квено

21
Я не думаю; я думаю, що це заслуговує проти, оскільки обмеження імені файлу / нового рядка є досить рідкісним і зазначеним вище. Повільніше? Можливо. Враховуючи, що ви запитуєте файлову систему, я підозрюю, що різниця в швидкості невелика. В моїх 10000 файлах я вимірюю різницю в 3 мс
Брайан Егню

8
Різниця в продуктивності між 'find <expr> | wc -l' та 'find <expr> -printf. | wc -c 'надзвичайно малі. Кешування (тобто, якщо ви виконуєте одну і ту ж знахідку двічі на одному дереві) набагато важливіше. ІМХО рішення з "wc -l" набагато інтуїтивніше.
шукач ям

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'

4

Це рішення, безумовно, повільніше, ніж деякі інші 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 байт) як роздільник циклу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.