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

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

3
15.03.2017, 06:41
3 ответа

Поскольку вы хотите анализировать только вывод ls , вы можете найти обычные файлы , размер которых меньше верхнего предела ( MAX байтов ) и ПРЕДПОЛАГАЯ без пробелов / новых строк в именах файлов, вы можете сделать следующее:

/bin/ls -l | awk -v MAX=150 '/^-/ && $5 <= MAX { print $NF }'
1
27.01.2020, 21:09

О чем следует помнить при анализе вывода команды ls -l :

  • формат зависит от локали. Формат указывается только POSIX в локали POSIX / C, и даже тогда он допускает некоторые вариации (например, количество интервалов между полями, ширину первого поля ...). Например, вы не можете легко обнаружить переносимые имена файлов, начинающиеся с пустых символов.
  • Многие системы позволяют пропускать пробелы в именах пользователей и групп, что делает надежный синтаксический анализ вывода практически невозможным. Лучше всего использовать ls -n (для использования числовых идентификаторов пользователей) вместо ls -l .
  • Невозможно надежно проанализировать вывод ls , если имена файлов могут содержать символы новой строки (а новая строка разрешена в имени файла практически во всех системах POSIX), если вы не используете -q (но тогда вы не можете указать точное имя файла, просто посмотрите представление в кавычках, из которого вы не сможете вернуться к исходному имени файла) или используйте нестандартные параметры, встречающиеся в некоторых реализациях. Хотя см. Также трюк ниже.
  • Поле size предоставляется не для всех типов файлов (а значение поля size зависит от системы для некоторых типов файлов). Вероятно, вы захотите ограничиться обычными файлами.
  • Приведенное выше предполагает POSIX ls . Известно, что в старых версиях были разные форматы вывода или отсутствовали пробелы между полями при некоторых обстоятельствах ...

Имея это в виду, при условии, что вы можете гарантировать, что имена файлов не содержат символов новой строки и не начинаются с пробелов, для перечисления обычных файлов, размер которых строго меньше 1 МБ, вы можете сделать:

(
  export LC_ALL=C
  ls -n | awk '
    /^-/ && $5 < 1048576 { 
      gsub(/([^[:blank:]]+[[:blank:]]+){8}/, "")
      print
    }'
)

​​Добавьте параметр -a , если вы хотите включить скрытые файлы. Добавьте -L , если для символических ссылок вы хотите рассмотреть файл, в который они (в конечном итоге) разрешаются.

Как говорили другие, правильным решением было бы использовать здесь find .

Уловка, позволяющая избежать появления новой строки и пробелов в начале.

Если вместо ls -n мы используем ls -nd ./*, мы сможем узнать, где начинается имя файла (на ./ ) и на какой строке он заканчивается (в строке перед следующим ./ ), поэтому вы можете сделать:

(
  export LC_ALL=C
  ls -nd ./* | awk '
    /\// {
      selected = (/^-/ && $5 < 1048576)
      sub(/.*\//, "./")
    }
    selected'
)

Однако обратите внимание, что это не сработает, если в папке много файлов. текущий каталог как ./* расширяется оболочкой, и это может привести к достижению ограничения на количество аргументов.

Чтобы включить скрытые файлы, -a здесь не поможет, нам нужно указать оболочке раскрыть их. POSIXly, это немного громоздко:

ls -dn ./..?* ./.[!.]* ./*

(что может вызвать предупреждающие сообщения об отсутствии файлов ./..?* или ./. [!.] * ).

3
27.01.2020, 21:09

Ваш подход неуклюж (и, честно говоря, неверен). Для таких задач существуют специальные инструменты, find - один из них.

Например, чтобы найти все файлы в текущем каталоге, размер которых меньше 1 MiB (1048576 Bytes), рекурсивно:

find . -type f -size -1048576c

Или с помощью оболочек, предоставляющих такие классификаторы glob на основе размера, например zsh, рекурсивно:

print -rl -- **/*(.L-1048576)

Здесь, в отличие от find выше, без скрытых файлов. Добавьте классификатор D glob, чтобы включить их.

8
27.01.2020, 21:09

Теги

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