Как получить количество файлов в каждом каталоге?

Вы можете сделать:

join -t, -a2 -11 -23 <(head -1 f1.txt; tail -n +2 f1.txt | \
         sort -t, -k1,1) <(head -1 f2.txt; tail -n +2 f2.txt | sort -t, -k3,3)
<() - синтаксис подстановки процесса, bash заменит его файловым дескриптором выходом команды внутри него, так как содержимое head -1 f1.txt; tail -n +2 f2.txt | sort -t, -k1,1 будет sort первый файл в первом поле из второй строки для отдыха, а первая строка добавлена ​​сверху, чтобы мы могли использовать его с join. То же самое касается f2.txt с полем sort в соответствии с тремя. join просто присоединяется к первому полю f1.txt и третью f2.txt в качестве общих полей.

Пример:

$ cat f1.txt 
DESCRIPTION,OrgIP,Service
Rob,1.1.1.1,Purple
John,2.2.2.2,Green
Mark,3.3.3.3,Yellow

$ cat f2.txt 
IP,MASK,DESCRIPTION
10.10.3.94,255.255.255.255,Rob
10.10.3.95,255.255.255.255,Mark
10.10.3.96,255.255.255.255,John

$ join -t, -11 -23 <(head -1 f1.txt; tail -n +2 f1.txt | sort -t, -k1,1) <(head -1 f2.txt; tail -n +2 f2.txt | sort -t, -k3,3)
DESCRIPTION,OrgIP,Service,IP,MASK
John,2.2.2.2,Green,10.10.3.96,255.255.255.255
Mark,3.3.3.3,Yellow,10.10.3.95,255.255.255.255
Rob,1.1.1.1,Purple,10.10.3.94,255.255.255.255
3
задан 11 January 2018 в 11:21

2 ответа

Попробуйте:

find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}' | sort -n

Если каталоги указаны в $@, используйте:

find "$@" -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}' | sort -n

Как это работает

find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' Это ищет все обычные файлы в каталогах dir1, dir2 и dir3. Для каждого найденного файла печатается его каталог. -maxdepth 1 (необязательно) говорит, что не следует погружаться в подкаталоги. -type f сообщает, что только сообщать об обычных файлах. Для каждого найденного файла -printf '%h\n' сообщает find для печати каталога, в котором находится файл. [F17] Это подсчитывает количество раз, когда каждый каталог появляется на входе. После того, как все данные были прочитаны, он распечатает итоговые значения. Мы используем ассоциативный массив c для подсчета количества просмотров каждой директории. В awk $0 отображается содержимое текущей строки. c[$0] - это количество раз, когда эта линия была видна до сих пор. c[$0]++ увеличивает счетчик на единицу. sort -n Сортирует вывод в порядке возрастания количества файлов. (-n говорит сортировать сортировку численно, а не в алфавитном порядке.)

Пример

Предположим, что у нас есть эти каталоги с этими файлами:

$ ls dir{1..3}/* dir1/a.txt dir1/c.txt dir1/e.txt dir1/f.txt dir2/b.txt dir2/d.txt dir2/f.txt dir3/b.txt dir1/b.txt dir1/d.txt dir1/file3.txt dir2/a.txt dir2/c.txt dir2/e.txt dir3/a.txt

Наша команда выводит результат:

$ find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}' | sort -n 2 dir3 6 dir2 7 dir1

Улучшение: добавление общей строки

$ find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; printf "%6i TOTAL",tot }' | sort -n 2 dir3 6 dir2 7 dir1 15 TOTAL

Чтобы подавить печать TOTAL, если на выходе есть только один каталог:

find "$@" -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' | sort -n

Включить пустые каталоги в выходном файле

Также включить пустые каталоги:

find "$@" -maxdepth 1 -type f -printf '%h\n' | awk 'FNR==NR{c[$0]=0; next} {c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' <(printf "%s\n" "$@") <(cat) | sort -n

В качестве примера рассмотрим пустой каталог:

$ ls dir4

И давайте установим $@:

$ set -- dir4

Теперь давайте запустим наш код:

$ find "$@" -maxdepth 1 -type f -printf '%h\n' | awk 'FNR==NR{c[$0]=0; next} {c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' <(printf "%s\n" "$@") <(cat) | sort -n 0 dir4

Давайте попробуем еще раз с двумя каталогами: [ ! d25] $ set -- dir1 dir4 $ find "$@" -maxdepth 1 -type f -printf '%h\n' | awk 'FNR==NR{c[$0]=0; next} {c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' <(printf "%s\n" "$@") <(cat) | sort -n 0 dir4 7 dir1 7 TOTAL

2
ответ дан 17 July 2018 в 23:22

Попробуйте:

find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}' | sort -n

Если каталоги указаны в $@, используйте:

find "$@" -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}' | sort -n

Как это работает

find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' Это ищет все обычные файлы в каталогах dir1, dir2 и dir3. Для каждого найденного файла печатается его каталог. -maxdepth 1 (необязательно) говорит, что не следует погружаться в подкаталоги. -type f сообщает, что только сообщать об обычных файлах. Для каждого найденного файла -printf '%h\n' сообщает find для печати каталога, в котором находится файл. [F17] Это подсчитывает количество раз, когда каждый каталог появляется на входе. После того, как все данные были прочитаны, он распечатает итоговые значения. Мы используем ассоциативный массив c для подсчета количества просмотров каждой директории. В awk $0 отображается содержимое текущей строки. c[$0] - это количество раз, когда эта линия была видна до сих пор. c[$0]++ увеличивает счетчик на единицу. sort -n Сортирует вывод в порядке возрастания количества файлов. (-n говорит сортировать сортировку численно, а не в алфавитном порядке.)

Пример

Предположим, что у нас есть эти каталоги с этими файлами:

$ ls dir{1..3}/* dir1/a.txt dir1/c.txt dir1/e.txt dir1/f.txt dir2/b.txt dir2/d.txt dir2/f.txt dir3/b.txt dir1/b.txt dir1/d.txt dir1/file3.txt dir2/a.txt dir2/c.txt dir2/e.txt dir3/a.txt

Наша команда выводит результат:

$ find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) printf "%6i %s\n",c[dir],dir}' | sort -n 2 dir3 6 dir2 7 dir1

Улучшение: добавление общей строки

$ find dir1 dir2 dir3 -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; printf "%6i TOTAL",tot }' | sort -n 2 dir3 6 dir2 7 dir1 15 TOTAL

Чтобы подавить печать TOTAL, если на выходе есть только один каталог:

find "$@" -maxdepth 1 -type f -printf '%h\n' | awk '{c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' | sort -n

Включить пустые каталоги в выходном файле

Также включить пустые каталоги:

find "$@" -maxdepth 1 -type f -printf '%h\n' | awk 'FNR==NR{c[$0]=0; next} {c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' <(printf "%s\n" "$@") <(cat) | sort -n

В качестве примера рассмотрим пустой каталог:

$ ls dir4

И давайте установим $@:

$ set -- dir4

Теперь давайте запустим наш код:

$ find "$@" -maxdepth 1 -type f -printf '%h\n' | awk 'FNR==NR{c[$0]=0; next} {c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' <(printf "%s\n" "$@") <(cat) | sort -n 0 dir4

Давайте попробуем еще раз с двумя каталогами: [ ! d25] $ set -- dir1 dir4 $ find "$@" -maxdepth 1 -type f -printf '%h\n' | awk 'FNR==NR{c[$0]=0; next} {c[$0]++} END{for (dir in c) {printf "%6i %s\n",c[dir],dir;tot+=c[dir]}; if (length(c)>1)printf "%6i TOTAL",tot }' <(printf "%s\n" "$@") <(cat) | sort -n 0 dir4 7 dir1 7 TOTAL

2
ответ дан 24 July 2018 в 13:53
  • 1
    Благодарю. Он работает очень хорошо. Я думаю, что лучше, если вы отредактируете свой ответ на использование & quot; $ @ & quot; чтобы соответствовать контексту вопроса. Есть также несколько мелких проблем. 1 - , если вы попросите wc -l подсчитать количество строк в пустом каталоге. он будет выводить 0, но ваш код ничего не выводит для пустых каталогов, которые могут быть немного запутанными. 2 - wc -l не отображает общую строку, если вы запрашиваете только один файл. Это довольно разумно. но в любом случае ваш код включает общее количество сырых продуктов. – yukashima huksay 11 January 2018 в 09:15
  • 2
    @yukashimahuksay Я обновил ответ, чтобы включить примеры, используя `$ @` `. Я также добавил код, который подавляет общее число, когда на выходе имеется только один каталог. Наконец, код предоставляется для перечисления пустых каталогов, имеющих нулевые файлы. – John1024 11 January 2018 в 10:53
  • 3
    Я попробовал последний код. Он работает только в том случае, если каталоги пусты! – yukashima huksay 11 January 2018 в 11:31
  • 4
    @yukashimahuksay Я просто проверил это, и вы абсолютно правы! Поскольку сейчас поздно, надеюсь, вы не возражаете, если я исправлю это завтра. – John1024 11 January 2018 в 11:52
  • 5
    @yukashimahuksay ОК. Я только что обновил ответ. Попытайтесь, и мы поговорим завтра. – John1024 11 January 2018 в 12:06

Другие вопросы по тегам:

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