Як змусити “wc -l” надрукувати лише кількість рядків без імені файлу?


155
wc -l file.txt

виводить кількість рядків та ім'я файлу.

Мені потрібно лише саме число (не назва файлу).

я можу це зробити

 wc -l file.txt | awk '{print $1}'

Але, можливо, є кращий спосіб?


13
wc -l < file.txtвиконує роботу точно і стисло.
Джонатан Леффлер


3
Це питання, яке я вже два рази шукав. Така поведінка туалету неінтуїтивна та антипарадигматична для -нікс звичайної терміновості. Ця лаконічність є чомусь, тому що ви точно не хочете обходити всілякі пухнасті надмірності. Зрештою, я знаю ім'я файлу, чи не так? Що я хочу - це кількість ліній.
Пітер - Відновіть Моніку

Відповіді:


217

Спробуйте таким чином:

wc -l < file.txt

5
У AIX, ksh, це завжди буде пробіл, який передує цифрі. Ми повинні використовувати | awk '{print $ 1}' або розріз, щоб обрізати пробіли. Ще одним способом обрізки буде додавання відлуння.
рао

@rao вірно, це додасть пробіл перед номером. Моє рішення вирішує це і простіше, ніж awk або cut.
Дезі Кокрайн

@rao Немає місця з bash. Звідки береться простір у кш? wc -lне повинен випромінювати його, і чому ksh передує стандартному виводу програми з пробілом?
Пітер - Відновіть Моніку

Хоча це правильне рішення (і досить просто, що туалет ніколи не змінювався), швидше за все, це повільніше і неінтуїтивно. Для одного, я б очікував щось подібне 4711 [stdin]як вихід.
Пітер - Відновіть Моніку

Також розгляньте створення пари з паром printf "%'d", який піклується про простір і добре друкує велику кількість.
Лев

21
cat file.txt | wc -l

Відповідно до довідкової сторінки (для версії BSD у мене немає версії GNU для перевірки):

Якщо жодні файли не вказані, використовується стандартний ввід і не відображається ім'я файлу. Підказка прийме введення до отримання EOF або [^ D] у більшості середовищ.


3
Мені не подобається кішка - конкатенація забирає багато часу.
PoGibas

9
wc -l < file.txtмає той же ефект.
pjmorse

@user: Перевірте. Напевно, найповільніша частина буде читанням файлу з диска.
sarnold

11
@ user1286528 тоді використовуйте, wc -l < file.txtщоб уникнути марного використання кота. Хоча ти абсолютно божевільний, якщо думаєш, що це вимагає будь-якого помітного часу.
варення

12

Щоб це зробити без провідного простору, чому б не:

wc -l < file.txt | bc

Я отримую синтаксичні помилки з цим (Ubuntu 14.04). Я думаю, що існує проблема з іменем файлу.
MERose

На RHEL 6.7 він викликає помилки: $ wc -l file.csv | bc (standard_in) 1: синтаксична помилка (standard_in) 1: незаконний символ: N (standard_in) 1: синтаксична помилка (standard_in) 1: синтаксична помилка
Rodrigo Hjort

3
Я також отримую помилку розбору, але ви можете поєднати це з іншою відповіддю, яку wc -l < file.txtпотрібно виправити помилку розбору та видалити пробіл:wc -l < file.txt | bc
jangosteve

11

Як щодо

wc -l file.txt | cut -d' ' -f1

тобто передаємо вихід wcна cut(де роздільники - пробіли і вибираємо лише перше поле)


4
це не краще, ніж wc -l file.txt | awk '{print $1}'спробував ОП.
подвійнеDown

1
Швидше, ніж wc -l < file.txtметод. Але потрібно використовувати | cut -d' ' -f2на BSD, доки wcкоманда повертає провідний простір, наприклад: "34068289 file.txt", а не "34068289 file.txt".
Sopalajo de Arrierez

@doubleDown добре, використовувати awk - це як використовувати верстат з ЧПУ для вирізання дошки замість пилки. Для пиляння використовуйте пилку.
Пітер - Відновіть Моніку

5

Порівняння методик

У мене була подібна проблема, що намагалася отримати кількість символів без провідних пробілів, наданих wc, що призвело мене до цієї сторінки. Після випробування відповідей тут наведені нижче результати мого особистого тестування на Mac (BSD Bash). Знову ж таки, це для підрахунку символів; для кількості ліній, які ви робили б wc -l. echo -nпропускає розрив кінцевої лінії.

FOO="bar"
echo -n "$FOO" | wc -c                          # "       3"    (x)
echo -n "$FOO" | wc -c | bc                     # "3"           (√)
echo -n "$FOO" | wc -c | tr -d ' '              # "3"           (√)
echo -n "$FOO" | wc -c | awk '{print $1}'       # "3"           (√)
echo -n "$FOO" | wc -c | cut -d ' ' -f1         # "" for -f < 8 (x)
echo -n "$FOO" | wc -c | cut -d ' ' -f8         # "3"           (√)
echo -n "$FOO" | wc -c | perl -pe 's/^\s+//'    # "3"           (√)
echo -n "$FOO" | wc -c | grep -ch '^'           # "1"           (x)
echo $( printf '%s' "$FOO" | wc -c )            # "3"           (√)

Я б не покладався на cut -f*метод в цілому, оскільки він вимагає знати точну кількість провідних пробілів, які може мати будь-який вихід. І той grepпрацює для підрахунку рядків, але не символів.

bcє найбільш стислим awkі, perlздається, трохи надмірним, але всі вони повинні бути досить швидкими та портативними.

Також зауважте, що деякі з них також можуть бути адаптовані для обрізки навколишнього пробілу із загальних рядків, а також (поряд із echo `echo $FOO`ще одним акуратним фокусом).


1
echo $(printf '%s' "$FOO" | wc -c)- один з рідкісних випадків, коли echoпідстановка команди не є марною.
трійка

@tripleee Whoa ... на основі вашого коду, echo `echo $FOO`;також діє як команда String.trim () для змінної! Це дивно зручно. Я також додам ваш рядок до своєї відповіді.
Beejor

Можливо, для контексту див. Також Коли обернути цитати навколо змінної оболонки
tripleee


4

Як щодо

grep -ch "^" file.txt

3
Приємно. Дуже оригінально / творче використання, grepале перевірка цього виявляється (не дивно) у 2–6 разів повільніше, ніж простіший / простий wcметод у моїх тестах.
аріельф

3

Очевидно, що для цього є багато рішень. Ось ще одна, хоча:

wc -l somefile | tr -d "[:alpha:][:blank:][:punct:]"

Це виводить лише кількість рядків, але символ символів нового рядка ( \n) присутній, якщо ви цього не хочете, замініть [:blank:]на [:space:].


У цьому виникає проблема, коли ім'я файлу має номер у ньому. Наприклад, для файлу test9з 1 рядком, вихід буде 19.
Рафаель Аренс

1

Найкращим способом було б насамперед знайти всі файли в каталозі, а потім використовувати AWK NR (кількість змінних записів)

нижче команда:

find <directory path>  -type f | awk  'END{print NR}'

приклад: - find /tmp/ -type f | awk 'END{print NR}'


0

Це працює для мене, використовуючи звичайний wc -lта sedзнімати будь-які символи, що не є числом.

wc -l big_file.log | sed -E "s/([a-z\-\_\.]|[[:space:]]*)//g"

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