Моє поточне рішення було б find <expr> -exec printf '.' \; | wc -c
, але це займає занадто багато часу, коли є більше 10000 результатів. Чи немає швидшого / кращого способу це зробити?
Відповіді:
Спробуйте замість цього (потрібно 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
рядок)
-printf '.'
Чому ні
find <expr> | wc -l
як просте портативне рішення? Оригінальне рішення - це створення нового процесу printf
для кожного знайденого окремого файлу, і це дуже дорого (як ви щойно знайшли).
Зауважте, що це перелічить, якщо у вас є вбудовані імена файлів із введеними новими рядками, але якщо у вас це є, то, підозрюю, ваші проблеми заглиблюються трохи глибше.
Це моя 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'
Це рішення, безумовно, повільніше, ніж деякі інші 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 байт) як роздільник циклу.