Якщо тихо стоїш у передпокої Unix & Linux і уважно слухаєш, то почуєш примарний голос, жалібно ридаючи: «А як з назви файлів, що містять нові рядки?»
ls -d *snp* | wc -l
або, що еквівалентно ,
printf "%s\n" *snp* | wc -l
виведе всі назви файлів, які містять snp, за кожним слідує новий рядок,
але також включить будь-які нові рядки у файли , а потім підрахує кількість рядків у висновку. Якщо є файл, ім'я якого
f o o
s n p \n
b a r
. t s v
тоді це ім'я буде записано як
foosnp
bar.tsv
що, звичайно, буде рахуватися як два рядки.
Є кілька альтернатив, які краще принаймні в деяких випадках:
printf "%s\n" * | grep -c snp
який рахує рядки, які містять snp, тому foosnp(\n)bar.tsvприклад зверху рахується лише один раз. Незначна зміна цього питання є
ls -f | grep -c snp
Вищеописані дві команди відрізняються тим, що:
- До складу
ls -fзаповіту будуть входити файли, імена яких починаються з .; цього printf … *немає, якщо не встановлено dotglobпараметр оболонки.
printf- вбудована оболонка; lsє зовнішньою командою. Тому, lsможливо, буде використано трохи більше ресурсів.
- Коли оболонка обробляє a
*, вона сортує імена файлів;
ls -fне сортує назви файлів. Тому lsможе використовуватися трохи менше ресурсів.
Але у них є щось спільне: вони будуть давати неправильні результати за наявності імен файлів, які містять новий рядок і мають snpі до, і після нового рядка .
Ще:
filenamelist=(*snp*)
echo ${#filenamelist[@]}
Це створює змінну масиву оболонок з переліком усіх імен файлів, які містять snp, а потім повідомляє про кількість елементів у масиві. Імена файлів трактуються як рядки, а не рядки, тому вбудовані нові рядки не є проблемою. Можна припустити, що такий підхід може мати проблеми, якщо каталог величезний, оскільки список імен файлів повинен міститись в оболонці.
Ще один:
Раніше, коли ми говорили printf "%s\n" *snp*, printfкоманда повторювала (повторно використовувала) "%s\n"рядок формату один раз для кожного аргументу в розширенні *snp*. Тут ми робимо невелику зміну в цьому:
printf "%.0s\n" *snp* | wc -l
Це повторить (повторно використовувати) "%.0s\n"рядок формату один раз для кожного аргументу в розширенні *snp*. Але "%.0s"означає надрукувати перші нульові символи кожного рядка - тобто нічого. Ця printfкоманда виведе лише новий рядок (тобто порожній рядок) для кожного файлу, що містить snpйого ім'я; а потім wc -lпорахує їх. І знову ж таки, ви можете включити .файли, встановивши dotglob.