Есть ли команда bash, которая подсчитывает количество файлов, которые соответствуют шаблону?
Например, я хочу получить количество всех файлов в каталоге, которые соответствуют этому шаблону: log*
Этот простой однострочный текст должен работать в любой оболочке, а не только в bash:
ls -1q log* | wc -l
ls -1q выдаст вам по одной строке на файл, даже если они содержат пробелы или специальные символы, такие как символы новой строки.
Выходные данные передаются в wc -l, который считает количество строк.
-l
, поскольку это требуетstat(2)
для каждого файла и для целей подсчета ничего не добавляет.ls
, так как он создает дочерний процесс.log*
расширяется оболочкой, нетls
, так что простойecho
будет делать.logs
, то будет учитываться и содержимое этого каталога журналов. Это, вероятно, не намеренно.Вы можете сделать это безопасно (то есть не будете ошибаться файлами с пробелами или
\n
их именами) с помощью bash:Вам нужно включить,
nullglob
чтобы вы не получили литерал*.log
в$logfiles
массиве, если не найдено ни одного файла. (См. Как «отменить» set -x для примеров того, как безопасно сбросить его.)источник
shopt -u nullglob
должен быть пропущен, еслиnullglob
он не был сброшен, тогда вы начали.*.log
только*
будет считать каталоги. Если файлы, которые вы хотите перечислить, имеют традиционное соглашение об именахname.extension
, используйте*.*
.Здесь много ответов, но некоторые не принимают во внимание
-l
)*.log
вместоlog*
logs
который соответствуетlog*
)Вот решение, которое обрабатывает все из них:
Объяснение:
-U
вызываетls
не сортировать записи, то есть не нужно загружать весь список каталогов в память-b
печатает экранирование в стиле C для неграфических символов, что принципиально приводит к тому, что переводы строк печатаются как\n
.-a
распечатывает все файлы, даже скрытые файлы (не требуется строго, когда глобус неlog*
подразумевает скрытых файлов)-d
распечатывает каталоги, не пытаясь составить список содержимого каталога, чтоls
обычно делается-1
удостоверяется, что он находится в одном столбце (ls делает это автоматически при записи в канал, поэтому это не является строго обязательным)2>/dev/null
перенаправляет stderr, чтобы при наличии 0 файлов журнала игнорировать сообщение об ошибке. (Обратите внимание, что вместо этогоshopt -s nullglob
можетls
быть указан весь рабочий каталог.)wc -l
использует список каталогов по мере его создания, поэтому выводls
никогда не находится в памяти в любой момент времени.--
Имена файлов отделяются от команды, используя их--
так, чтобы их нельзя было понимать как аргументыls
(в случаеlog*
удаления)Оболочка будет расширяться
log*
в полный список файлов, которые могут исчерпать память , если много файлов, поэтому затем запустить его через Grep это лучше:Последний обрабатывает очень большие каталоги файлов без использования большого количества памяти (хотя и использует подоболочку). В
-d
этом больше нет необходимости, потому что он только перечисляет содержимое текущего каталога.источник
Для рекурсивного поиска:
wc -c
будет подсчитывать количество символов в выводеfind
, а-printf x
подскажетfind
распечататьx
для каждого результата.Для нерекурсивного поиска сделайте это:
источник
-name '*.log'
он будет считать все файлы, что мне и понадобилось для моего варианта использования. Также флаг -maxdepth чрезвычайно полезен, спасибо!find
; просто напечатайте что-то еще, кроме имени файла.Принятый ответ на этот вопрос неправильный, но у меня низкая репутация, поэтому я не могу добавить к нему комментарий.
Правильный ответ на этот вопрос дает Мат:
Проблема с принятым ответом состоит в том, что wc -l считает количество символов новой строки и считает их, даже если они выводят на терминал как «?» в выводе 'ls -l'. Это означает, что принятый ответ НЕУДАЧЕТ, когда имя файла содержит символ новой строки. Я проверил предложенную команду:
и он ошибочно сообщает значение 2, даже если существует только 1 файл, соответствующий шаблону, имя которого содержит символ новой строки. Например:
источник
Если у вас много файлов и вы не хотите использовать элегантное
shopt -s nullglob
решение и массив bash, вы можете использовать find и т. Д., Если вы не распечатываете имя файла (которое может содержать символы новой строки).Это найдет все файлы, которые соответствуют log * и не начинаются с
.*
- «not name. *» Избыточно, но важно отметить, что по умолчанию для «ls» не показываются точечные файлы, но по умолчанию для поиска, чтобы включить их.Это правильный ответ, и он обрабатывает любое имя файла, которое вы можете использовать, потому что имя файла никогда не передается между командами.
Но
shopt nullglob
ответ - лучший ответ!источник
find
против использованияls
двух разных способов решения проблемы.find
не всегда присутствует на машине, ноls
обычно есть,find
вероятно, не имеет всех этих причудливых вариантовls
ни для одного.-maxdepth 1
find
делает это по умолчанию. Это может создать путаницу, если вы не поймете, что есть скрытая дочерняя папка, и может сделать его выгоднымls
в некоторых случаях, когда по умолчанию не отображаются скрытые файлы.Вот мой единственный вкладыш для этого.
источник
set --
что ничего не делает, кроме как подготовить нас к тому$#
, что хранит количество аргументов командной строки, которые были переданы программе оболочкиВы можете использовать опцию -R, чтобы найти файлы вместе с файлами внутри рекурсивных каталогов.
Вы можете использовать шаблоны на grep
источник
Важный комментарий
(недостаточно репутации, чтобы комментировать)
Это БАГГИ :
Если
shopt -s nullglob
он установлен, он печатает количество ВСЕХ обычных файлов, а не только файлы с шаблоном (протестировано на CentOS-8 и Cygwin). Кто знает, что имеют другие бессмысленные ошибкиls
?Это ПРАВИЛЬНО и намного быстрее:
Это делает ожидаемую работу.
И время работы отличается.
1-й:
0.006
на CentOS и0.083
Cygwin (если он используется с осторожностью).2-й:
0.000
на CentOS и0.003
на Cygwin.источник
Вы можете легко определить такую команду, используя функцию оболочки. Этот метод не требует никакой внешней программы и не порождает дочерний процесс. Он не пытается выполнить опасный
ls
анализ и обрабатывает «специальные» символы (пробелы, переводы строки, обратные слэши и т. Д.) Просто отлично. Он опирается только на механизм расширения имени файла, предоставляемый оболочкой. Он совместим как минимум с sh, bash и zsh.Строка ниже определяет вызываемую функцию,
count
которая печатает количество аргументов, с которыми она была вызвана.Просто назовите его с нужным рисунком:
Чтобы результат был корректным, когда шаблон глобализации не соответствует, опция оболочки
nullglob
(илиfailglob
- это поведение по умолчанию в zsh) должна быть установлена во время расширения. Это может быть установлено так:В зависимости от того, что вы хотите посчитать, вас также может заинтересовать опция оболочки
dotglob
.К сожалению, по крайней мере, с bash, нелегко установить эти параметры локально. Если вы не хотите устанавливать их глобально, самое простое решение - использовать функцию более замысловато:
Если вы хотите восстановить легкий синтаксис
count log*
или действительно хотите избежать порождения подоболочки, вы можете взломать что-то вроде:В качестве бонуса эта функция имеет более общее использование. Например:
Превратив функцию в файл сценария (или эквивалентную программу на C), вызываемую из PATH, ее также можно составить из таких программ, как
find
иxargs
:источник
Я много думал об этом ответе, особенно учитывая материал не-parse-ls . Сначала я попробовал
который работал, если было только имя файла, как
но не удалось, если я сделал имя файла, как это
Я наконец-то придумал, что я ставлю ниже. Обратите внимание, что я пытался получить количество всех файлов в каталоге (не включая какие-либо подкаталоги). Я думаю, что наряду с ответами @Mat и @Dan_Yard, а также наличием по крайней мере большинства требований, изложенных @mogsie (я не уверен насчет памяти.) Я думаю, что ответ @mogsie правильный, но я всегда стараюсь держаться подальше от разбора,
ls
если это не очень специфическая ситуация.Более читабельно:
Это делается для поиска файлов, ограничивая вывод нулевым символом (чтобы избежать проблем с пробелами и переводами строк), а затем подсчитывает количество нулевых символов. Количество файлов будет на один меньше количества нулевых символов, так как в конце будет нулевой символ.
Чтобы ответить на вопрос ФП, необходимо рассмотреть два случая.
1) нерекурсивный поиск:
2) Рекурсивный поиск. Обратите внимание, что то, что находится внутри
-name
параметра, может потребоваться изменить для немного другого поведения (скрытые файлы и т. Д.).Если кто-то хотел бы прокомментировать, как эти ответы сравниваются с теми, которые я упомянул в этом ответе, сделайте это.
Обратите внимание, я получил этот мыслительный процесс, получая этот ответ .
источник
Вот что я всегда делаю:
источник
awk 'END{print NR}'
должны быть эквивалентныwc -l
.Это означает, что нужно перечислить один файл в строке, а затем передать его команде word count с переключением параметров на счетчик строк.
источник
Чтобы посчитать все, просто отправьте ls в строку подсчета слов:
Чтобы сосчитать с шаблоном, сначала нужно выполнить поиск по трубе
источник