Сокеты Unix надежны. Если читающий не читает, пишущий блокирует. Если сокет является дейтаграммным, каждая запись сопровождается чтением. Если сокет является потоковым, ядро может буферизировать некоторые байты между пишущим и читающим, но когда буфер заполнен, пишущий блокируется. Данные никогда не отбрасываются, за исключением буферизованных данных, если читатель закрывает соединение до чтения буфера.
Поскольку вы хотите анализировать только вывод ls
, вы можете найти обычные файлы
, размер которых меньше верхнего предела ( MAX байтов
) и ПРЕДПОЛАГАЯ
без пробелов / новых строк в именах файлов, вы можете сделать следующее:
/bin/ls -l | awk -v MAX=150 '/^-/ && $5 <= MAX { print $NF }'
О чем следует помнить при анализе вывода команды ls -l
:
ls -n
(для использования числовых идентификаторов пользователей) вместо ls -l
. ls
, если имена файлов могут содержать символы новой строки (а новая строка разрешена в имени файла практически во всех системах POSIX), если вы не используете -q
(но тогда вы не можете указать точное имя файла, просто посмотрите представление в кавычках, из которого вы не сможете вернуться к исходному имени файла) или используйте нестандартные параметры, встречающиеся в некоторых реализациях. Хотя см. Также трюк ниже. 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 ./..?* ./.[!.]* ./*
(что может вызвать предупреждающие сообщения об отсутствии файлов ./..?*
или ./. [!.] *
).
Ваш подход неуклюж (и, честно говоря, неверен). Для таких задач существуют специальные инструменты, find
- один из них.
Например, чтобы найти все файлы в текущем каталоге, размер которых меньше 1 MiB (1048576 Bytes), рекурсивно:
find . -type f -size -1048576c
Или с помощью оболочек, предоставляющих такие классификаторы glob на основе размера, например zsh
, рекурсивно:
print -rl -- **/*(.L-1048576)
Здесь, в отличие от find
выше, без скрытых файлов. Добавьте классификатор D
glob, чтобы включить их.