получить минимальное и максимальное количество строк из файлов в каталоге

Вы можете использовать csplitдля разделения на отдельные файлы.

sudo ssldump -i enp0s8 -a -A -H -n -x | csplit - '/^New TCP connection/'

Это разделит ввод на 100 файлов с именами от xx00до xx99.

Вы можете установить префикс (по умолчаниюxx)на что-то другое, используя опцию --prefix=somethingelse.

Количество цифр, используемых для подсчета файлов (по умолчанию 2 ), можно установить с помощью --digits=X.

Вам может понадобиться использовать опцию --keep-files, если csplitудаляет сгенерированные файлы, когда вы останавливаете процесс (это может интерпретировать прерывание как сбой ).

0
29.09.2020, 00:46
3 ответа

Вы можете использовать findдля создания списка файлов и передачи его дальше. Это позволяет избежать попытки оболочки раскрыть все пять миллионов имен файлов одной командой

.
LC_ALL=C find -type f -exec wc -l {} + |
    awk '
        $2 != "total" {
            if (max=="" || $1>max) {max=$1; mxf=$2};
            if (min=="" || $1<min) {min=$1; mnf=$2};
        }
        END { printf "Min %d for %s, max %d for %s\n", min, mnf, max, mxf }
    '

findгенерирует список из count имя файла , который передается сценарию awk. Это, в свою очередь, делает тяжелую работу, ища -и сообщая о -максимальное и минимальное значение и имя файла.

Этот упрощенный код не обрабатывает имена файлов, содержащие пробелы или непечатаемые -символы.

3
18.03.2021, 23:01

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

find /some/data/dir/with/text/files/ -type f -print | xargs wc -l

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

Это, по общему признанию, включает в себя удержание большого количества данных в процессе вычисления информации, которую вы ищете, поэтому, возможно, лучше направить вывод конвейера find | xargsв скрипт awk. который просто проходит через каждую строку, а затем отслеживает, меньше ли количество каждой строки, чем минимум, который он видел до сих пор, или больше, чем максимум, который он видел до сих пор.

2
18.03.2021, 23:01

С последними версиями утилит GNU:

(
  printf '/dev/null\0' # for the case where's there's only one file
  find. -type f -print0
) |
  wc --files0-from=- -l |
  sed '1d;$d' | # remove /dev/null and total
  sort -n |
  sed '1b;$b;d'

Здесь мы передаем список файлов из findв wcпо конвейеру в wcstdin, а не через аргументы, поэтому у этого есть несколько преимуществ :нет ограничений на количество аргументы, так как мы не используем системный вызов execve(). wcможет начать чтение файлов, как только findих найдет. По сравнению с решениями xargsили -exec {} +выполняется только один вызов wc, поэтому мы получаем максимум одну строку total.

Обратите внимание, что GNU wc8.30, по крайней мере, искажает имена файлов, которые содержат символы новой строки. Например, файл с именем ./a<newline>bотображается здесь как'./a'$'\n''b'(с использованием стиля ksh93 -$'...'с кавычками для выражения символа новой строки как$'\n'). В этом случае вы можете сказать, когда wcделает это искажение, поскольку все пути к файлам должны начинаться с .. Поэтому, когда вы видите ', это означает, что было выполнено искажение.

Вы можете отменить это в оболочке zshс флагом расширения параметра Q:

$ wc -l './a
b'
146 './a'$'\n''b'
$ !! | read -r length file
$ printf '<%s>\n' $file ${(Q)file}
<'./a'$'\n''b'>
<./a
b>

В общем случае вы не можете сказать, когда wcделает это искажение, хотя, например, оно будет отображать имя файла a<newline>bили 'a'$'\n''b'одинаково:

$ wc -l 'a
b' "'a'$'\n''b'"
  146 'a'$'\n''b'
    1 'a'$'\n''b'
  147 total
3
18.03.2021, 23:01

Теги

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