Как я могу получить количество файлов в каталоге с помощью командной строки?

  • egrep 100%-й эквивалент grep -E
  • fgrep 100%-й эквивалент grep -F
  • Исторически эти переключатели были обеспечены в отдельных двоичных файлах. В некоторых действительно старых системах Unix Вы найдете, что необходимо назвать отдельные двоичные файлы, но во всех современных системах предпочтены переключатели. Страница справочника для grep имеет детали об этом.

    Что касается того, что они делают, -E переключатели grep в специальный режим так, чтобы выражение было оценено как ДО (Расширенное регулярное выражение) в противоположность его нормальному сопоставлению с образцом. Детали этого синтаксиса находятся на странице справочника.

    -E, --extended-regexp
    Интерпретируйте ШАБЛОН как расширенное регулярное выражение

    -F переключитесь переключает grep в другой режим, где он принимает, что шаблон соответствует, но затем разделяет тот шаблон на одну строку поиска на строку и делает ИЛИ ищет на любой из строк, не делая никакого специального сопоставления с образцом.

    -F, --fixed-strings
    Интерпретируйте ШАБЛОН как список фиксированных строк, разделенных новыми строками, любая из которых должна быть подобрана.

    Вот некоторые сценарии в качестве примера:

    • У Вас есть файл со списком, говорят что десять имен пользователей Unix в простом тексте. Вы хотите искать файл группы на своей машине, чтобы видеть, находится ли какой-либо из этих десяти перечисленных пользователей в каких-либо специальных группах:

      grep -F -f user_list.txt /etc/group
      

      Причина -F переключатель помогает, вот то, что имена пользователей в Вашем файле шаблона интерпретируются как строки обычного текста. Точки, например, были бы интерпретированы как точки, а не подстановочные знаки.

    • Вы хотите искать использование необычного выражения. Например, круглая скобка () может использоваться для указания на группы с | используемый в качестве операции ИЛИ. Вы могли выполнить это поисковое использование -E:

      grep -E '^no(fork|group)' /etc/group
      

      ... к возвратным линиям, которые запускаются или с "nofork" или с "nogroup". Без -E переключатель необходимо было бы выйти из специальных символов, включенных, потому что с нормальным сопоставлением с образцом они будут просто искать тот точный шаблон;

      grep '^no\(fork\|group\)' /etc/group
      
207
24.08.2010, 00:49
18 ответов

Используя широкое определение "файла"

ls | wc -l

(обратите внимание, что это не считает скрытые файлы и предполагает, что имена файлов не содержат символы новой строки).

Включать скрытые файлы (кроме . и ..) и избегайте проблем с символами новой строки, канонический путь:

find . ! -name . -prune -print | grep -c /

Или рекурсивно:

find .//. ! -name . -print | grep -c //
263
27.01.2020, 19:27
  • 1
    wc программа "для подсчета количества слов". -l переключитесь заставляет это считать строки. В этом случае это считает строки в выводе от ls. Это всегда способ, которым мне преподавали добраться, файл значат данный каталог, также. –  Sandy 24.08.2010, 09:07
  • 2
    добавьте примечание это ls делает ls -1 если вывод является каналом. –  lesmana 24.08.2010, 19:47
  • 3
    , который не получает все в каталоге - Вы пропустили точечные файлы и собираете пару дополнительных строк, также. Пустой каталог все еще возвратит 1 строку. И если Вы звоните ls -la, Вы получите три строки в каталоге. Вы хотите ls -lA | wc -l пропускать . и .. записи. Вы все еще будете off-one, как бы то ни было. –   25.08.2010, 18:14
  • 4
    Пустой каталог возвращается 0 для меня –  James Roth 24.09.2013, 05:16
  • 5
    исправленный подход, который не удвоил бы файлы количества с новыми строками на имя, будет этим: ls -q | wc -l - хотя примечание, что скрытые файлы все еще не будут считаться этим подходом и этим каталоги, будет считаться. –  godlygeek 04.03.2015, 00:30

Вот другая техника вроде той, которую отправил Gilles:

word_count () { local c=("$@"); echo "${#c[@]}"; }
file_count=$(word_count *)

который создает массив с 13 923 элементами (если это - то, сколько файлы там).

1
27.01.2020, 19:27
  • 1
    Какой смысл этого c массив? word_count() { echo "$#"; } был бы достаточно. Точка @Gilles решения должна сохранить количество в возвращенной переменной, чтобы избежать необходимости использовать замену команды (который включает ветвление и канал в оболочках кроме ksh93). –  Stéphane Chazelas 01.03.2016, 18:27

Если Вы знаете, что текущий каталог содержит по крайней мере один нескрытый файл:

set -- *; echo "$#"

Это очевидно generalizable к любому шарику.

В сценарии это имеет иногда неудачный побочный эффект перезаписи позиционных параметров. Можно работать вокруг этого при помощи подоболочки или с функцией (версия Границы/POSIX) как:

count_words () {
  eval 'shift; '"$1"'=$#'
}
count_words number_of_files *
echo "There are $number_of_files non-dot files in the current directory"

Альтернативное решение $(ls -d -- * | wc -l). Если шарик *, команда может быть сокращена к $(ls | wc -l). Парсинг вывода ls всегда делает меня обеспокоенным, но здесь это должно работать, пока Ваши имена файлов не содержат новые строки или Ваш ls выходит из них. И $(ls -d -- * 2>/dev/null | wc -l) имеет преимущество обработки случая шарика несоответствия корректно (т.е. это возвращается 0 в этом случае, тогда как set * метод требует трудного тестирования, если шарик мог бы быть пустым).

Если имена файлов могут содержать символы новой строки, альтернатива должна использовать $(ls -d ./* | grep -c /).

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

8
27.01.2020, 19:27
  • 1
    Вы действительно хотите создать 13 923 позиционных параметра? И необходимо сделать локальную переменную local или устраните его: eval $1=$# или просто используйте echo $# и сделайте number_of_files=$(count_words *). –  Paused until further notice. 24.08.2010, 04:16
  • 2
    @Dennis: часть точки должна была постараться не разветвляться. Я предполагаю, что это не беспокойство 21-го века. Хорошо, я признаю, что больше не забочусь об оболочках неPOSIX, таким образом, я, возможно, избежал временной переменной. –  Gilles 'SO- stop being evil' 24.08.2010, 10:14
  • 3
    Почему Вы вычитали один из $# (Вы не сделали этого до редактирования)? –  Paused until further notice. 25.08.2010, 01:12
  • 4
    @Dennis: я все еще избегаю ветвления (хорошо, это действительно имеет значение на машинах с медленным ЦП, таких как маршрутизаторы), и передача имени переменной как $1. Таким образом, то, что я хочу считать, является количеством параметров, которые не являются первым параметром. (Я не могу использовать shift потому что я должен иметь в наличии имя переменной.) (Umm, теперь если Вы спросили о первой строке...), –  Gilles 'SO- stop being evil' 25.08.2010, 01:42
  • 5
    @Dennis: задумайтесь о нем, я могу использовать shift если я время это право. –  Gilles 'SO- stop being evil' 25.08.2010, 01:50
ls -1 | wc -l

...

$ ls --help | grep -- '  -1'
    -1                         list one file per line

...

$ wc --help | grep -- '  -l'
    -l, --lines            print the newline counts

PS: Отметьте ls - <номер один> | туалет - <буква L>

15
27.01.2020, 19:27
  • 1
    Большинство версий ls сделать -1 автоматически, когда вывод к каналу. –  Paused until further notice. 24.08.2010, 04:01
  • 2
    @Dennis это интересно, я не знал, что приложение могло сказать, что его вывод шел в канал. –  xenoterracide 24.08.2010, 08:35
  • 3
    I + 'редактор эта версия, так как это более явно. Хотя, да ls действительно использует-1, если он передал по каналу (попробуйте его: ls | кошка), я нахожу-1 синтаксис более явным. –  gabe. 24.08.2010, 21:13
  • 4
    @xenoterracide точки: В Bash: [[ -p /dev/stdin ]] && echo "stdin is from a pipe" –  Paused until further notice. 26.08.2010, 01:42
  • 5
    В моих тестах это было значительно быстрее, чтобы также предоставить-f возможность избегать ls сортировка имен файлов. К сожалению, Вы все еще получаете неправильный ответ, если Ваши имена файлов содержат новые строки. –  Samuel Edwin Ward 08.01.2013, 22:42

Для узкого определения файла:

 find . -maxdepth 1 -type f | wc -l
32
27.01.2020, 19:27
  • 1
    И можно, конечно, опустить -maxdepth 1 для подсчета файлов рекурсивно (или корректируют его для желаемой макс. поисковой глубины). –  user7089 03.08.2014, 19:25
  • 2
    Если у Вас будет файл, имя которого содержит новую строку, этот подход будет неправильно считать его дважды. –  godlygeek 04.03.2015, 00:20
  • 3
    исправленный подход, который не удвоил бы файлы количества с новыми строками на имя, будет этим: find -maxdepth 1 -type f -printf "\n" | wc -l –  godlygeek 04.03.2015, 00:27
  • 4
    +1 Допускает скрытые файлы, и игнорирует каталоги –  Michael Durrant 13.03.2015, 01:56

Ни трубы, ни копии строки, ни вилки, просто баш один лайнер

$ fcount() { local f i=0; for f in *; do let i++; done; echo $i; }; fcount
1
27.01.2020, 19:27

После установки дерева просто введите:

tree

Если вам нужны еще и скрытые файлы:

tree -a

Если вы используете Debian / Mint / Ubuntu Linux, то введите следующую команду для установки дерева:

sudo apt-get install tree

Опция -L используется для указания максимального уровня отображения дерева каталогов. Команда дерева подсчитывает не только количество файлов, но и количество каталогов, учитывая количество уровней дерева каталогов по вашему желанию.

4
27.01.2020, 19:27
d=0; set ./somedirname                         #init dir counter; name
for f in ./*                                   #glob current dir
do   [ -f "$f" ] && set "$f" "$@" &&           #if "$f" is file and...
     [ "$d" -lt "$((d+=$#>5))" ]  || continue  #d<(d+($#>5)) or continue
     mkdir "$6$d" && mv "$@$d"    || !  break  #mk tgtdir and mv 5 files or
     shift 5                                   #break with error
done

Приведенная выше команда использует способность arg-массива оболочки связывать строки с головой и хвостом. Например, если вы написали функцию:

fn(){ printf '<%s>\n' "42$@"; }

... и назвали ее как:

fn show me

... она бы напечатала:

<42show>
<me>

... потому что вы можете добавить или добавить к первому или последнему элементу (соответственно) в массиве arg, просто заключив его кавычки вокруг предварительно прикрепленной строки.

Массив arg выполняет двойную функцию здесь также в том смысле, что он также служит счетчиком - параметр оболочки $ # всегда даст нам точную информацию о том, сколько элементов мы сложили до сих пор.

Но... Вот шаг за шагом:

  1. d = 0; set ./somedirname
    • Параметр $ d var увеличивается на единицу для каждого созданного нового каталога. Здесь он инициализируется как ноль.
    • ./somedirname - это то, что вам нравится. Префикс ./ важен хотя - не только он наверняка корнит все операции в текущий каталог, но и позволяет указать любой тип имени, который вы хотели бы (если вы хотите сойти с ума и использовать новые строки или начать его с дефисов вы можете безопасно - но это, вероятно, не рекомендуется) . Поскольку имя argname всегда начинается с ./ ни одна команда не будет неверно интерпретировать его как параметр в командной строке.
  2. для f in ./*
    • При этом запускается цикл по всем (при наличии) соответствий для * в текущем каталоге. Опять же, каждое совпадение имеет префикс ./.
  3. [-f "$ f"]
    • проверяет, является ли совпадение каждой итерации обычным файлом (или ссылкой на него) и...
  4. set "$ f" "$ @"
    • размещает совпадения один перед другим в массиве оболочки. Таким образом, ./somedirname всегда находится в конце массива.
  5. ["$ d" -lt "$ ((d + = $ # > 5))"]
    • добавляет 1 к $ d при наличии более 5 элементов массива в "$ @" при одновременной проверке результата на приращение.
  6. | | continue
    • Если один из наборов [-f "$ f"] ... ["$ d" -lt... Команды не возвращают значение true, цикл продолжается до следующей итерации и не пытается завершить остальную часть цикла. Это эффективно и безопасно.
  7. mkdir "$6 $ d"
    • Поскольку предложение continue гарантирует, что мы сможем достичь этого только в том случае, если $ # > 5 наше ./somedirname теперь находится в $6 и значение $ d было только что увеличено на единицу. Таким образом, для первой группы 5 файлов, соответствующих и перемещаемых, создается каталог с именем ./somedirname1 и для пятой ./somedirname5 и так далее. Важно отметить, что эта команда завершается неуспешно , если уже существует какой-либо путь с целевым путем. Другими словами,эта команда является только успешной, если каталог с таким именем уже не существует.
  8. mv «$ @ $ d»

    • Это расширяет массив при добавлении значения $ d к хвосту последнего элемента - имени целевого каталога. Таким образом, он расширяется как:

    mv ./file5 ./file4 ./file3 ./file2 ./file1 ./somedirname1

    • ... именно этого вы и хотите.
  9. || ! break

    • Если ни одна из двух предыдущих команд не выполнена успешно по какой-либо причине, для loop break s. ! отправляет логическое обратное значение возврата break , которое обычно равно нулю, поэтому break возвращает 1. Таким образом, цикл возвращает значение false в случае возникновения какой-либо ошибки в любой из предыдущих команд. Это важно - для циклов - в отличие от , пока/до циклов - не подразумевает тестов, только итерацию. Без явного тестирования возврата этих двух команд оболочка не обязательно остановится на ошибке - и set -e , вероятно, полностью уничтожит родительскую оболочку. Скорее это обеспечивает значимую отдачу и то, что цикл не будет продолжать итерацию, если что-то пойдет не так.

    • На первый взгляд, кажется, что это единственный ответ, который остановится, например, если mkdir ./somedirname не вернется истинным - все остальные будут продолжать закольцовываться (и, вероятно, повторит ошибку или, что еще хуже, переместит файлы в текущем каталоге в существующий каталог и, возможно, в другие файлы с тем же именем) . При работе с произвольными именами файлов в циклах следует всегда проверять наличие исходного файла и на наличие целевого объекта.

  10. shift 5
    • Этот shift отбрасывает первые 5 элементов в arg-массиве оболочки, что возвращает ./somedirname в $1 и сбрасывает состояние массива для следующей итерации.
-121--97729-

С помощью этой неловкой программы можно создавать команды оболочки и, в случае сомнений, заранее проверять их правильность...

awk -v n=5 '{ printf "mv \"%s\" %s\n", $0, "direc" int((NR-1)/n)+1 }' list

Если выходной канал работает нормально, вся команда переходит в sh . Кроме того, если вы хотите избежать дополнительного файла «list», вы можете создать его на лету; вся программа будет тогда...

ls  |  awk -v n=5 '{ printf "mv \"%s\" %s\n", $0, "direc" int((NR-1)/n)+1 }'  |  sh

Можно определить другие значения, отличные от 5, если изменить настройку n = 5.

Если вы также хотите создать целевые каталоги на лету, вот вариант...

ls  |  awk -v n=5 '
         NR%n==1 { ++c ; dir="direc"c ; print "mkdir "dir }
         { printf "mv \"%s\" %s\n", $0, dir }
'  |  sh
-121--97730-

Возможно, наиболее полным ответом с помощью пары ls / wc является

ls -Aq | wc -l

, если требуется считать файлы точек, и

ls -q | wc -l

в противном случае.

  • -A - считать файлы точек, но пропустить . и .. .
  • -q заменить ls неграфические символы, в частности символ новой строки, на ? ,создание 1 строки вывода для каждого файла

Чтобы получить однострочный вывод от ls в терминале (т.е. без прокладки его в wc ), необходимо добавить опцию -1 .

(поведение ls , протестированное на coreutils 8,23)

11
27.01.2020, 19:27

Используйте команду дерево , просто:

tree
-2
27.01.2020, 19:27

Это зависит. Если вы собираетесь к двойной загрузке, то вам нужно установить его на жесткий диск. Этот тип установки обеспечивает исключительную мощность ресурсов для ОС. Второй вариант - использование USB Live boot или Persistence Live USB или Encrypted Live USB Persistence. Третий вариант - Virtualbox или VMware, но для этого ваш ПК должен иметь не меньше 8GB оперативной памяти для обеспечения бесперебойной работы и более безопасной. Если что-то случится, просто удалите машину. Более того, вероятность заражения хост-машины редка.

-121--248659-

Использование AWK для подсчета строк в файле

awk 'END {print NR}' filename
-121--2498-

При использовании пары ls/wc, если мы добавляем -U, это будет намного быстрее (не сортируйте).

ls -AqU | wc -l
5
27.01.2020, 19:27

Попробуйте это, надеюсь, этот ответ вам поможет

echo $((`ls -l | wc -l` -1 ))
0
27.01.2020, 19:27

Вы можете проверить:

ls -l | grep -v ^l | wc -l
0
27.01.2020, 19:27
find . -type f -maxdepth 1 |  wc -l 

Это может вывести список только файлов в текущем каталоге.

1
27.01.2020, 19:27
find -maxdepth 1 -type f -printf . | wc -c
  • -maxdepth 1 сделает его нерекурсивным, find будет рекурсивным по умолчанию
  • -тип f будет включать только файлы
  • -printf. - это мило. он печатает точку для каждого файла вместо имени файла, и теперь он может обрабатывать любое имя файла, а также сохраняет данные; нам просто нужно посчитать точки :)
  • | wc -c подсчитывает символы
3
27.01.2020, 19:27

Улучшение некоторых ответов, данных ранее, но на этот раз явно.

$ tree -L 1 | tail -n 1 | cut -d " " -f 3

Стоит отметить использование некоторых любимых команд, таких как tail и cut . Также обратите внимание, что дерево по умолчанию недоступно. Приведенная выше команда сначала захватывает информацию о каталоге на уровне 1, затем получает последнюю строку tail -n 1 , где находится наша цель, и заканчивает cut , чтобы взять третье слово.

Например, указав в / :

/ $ tree -L 1
.
├── 1
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib64 -> usr/lib64
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

20 directories, 1 file
/ $ tree -L 1 | tail -n 1
20 directories, 1 file
/ $ tree -L 1 | tail -n 1 | cut -d " " -f 3
1

А как насчет того, чтобы спросить количество каталогов?

0
27.01.2020, 19:27

Я нашел du --inodesполезным, но не уверен, какая версия duдля этого требуется. Это должно быть значительно быстрее, чем альтернативные подходы с использованием findи wc.

В Ubuntu 17.10 работает следующее:

du --inodes      # all files and subdirectories
du --inodes -s   # summary
du --inodes -d 2 # depth 2 at most

Объедините с | sort -nrдля сортировки по убыванию количества содержащих инодов.

20
27.01.2020, 19:27

В Linux, чтобы сделать команду очень надежной и обрабатывать файлы, имена которых могут содержать новые строки, используйте это:

find -maxdepth 1 -type f -print0 | tr -cd '\0' | wc -c

Это спасает нас от тяжелого разбора lsвывода.


Связанные:

1
27.01.2020, 19:27

Если у вас есть права на установку пакетов, есть очень простой инструмент для этого (и многое другое ). Он называется ncduи может быть установлен с помощью apt или yum. Основное использование ncdu было бы:

ncdu /path/to/dir

Отобразится экран на основе ncurses -, по которому можно перемещаться с помощью клавиш курсора. Внизу изначально вы увидите общее количество файлов в этом каталоге и подкаталогах. Используя клавиши со стрелками вверх/вниз и ENTER, вы можете быстро перейти к любому каталогу и получить статистику использования.

Немного продвинутое использование — ncdu -x /path/to/dir, которое будет учитывать только те файлы и каталоги, которые находятся в той же файловой системе, что и сканируемый каталог.

Преимущество ncdu в том, что во время сканирования отображается индикатор выполнения. Вы также можете перенаправить вывод в файл для последующего использования.

На справочной странице есть интересный раздел о том, как обрабатываются жесткие ссылки в различных версиях ncdu.

ХТН.

0
19.08.2020, 04:42

Теги

Похожие вопросы