Очень интересный вопрос. Обычно цель каждого - сделать свою раздачу как можно легче. Также я думаю, что нет большой разницы между различными дистрибутивами базовой установкой , поскольку в большинстве из них используются более или менее одинаковые вещи (графический интерфейс, ядро Linux, файловая система и т. Д.). Итак, чтобы дать вам какой-то ответ, я дам вам несколько цифр в соответствии с наиболее часто используемыми веб-сайтами дистрибутивов:
Debian:
Ubuntu
Linux Mint
Fedora
Как вы можете видеть, все перечисленные выше требуют более или менее тех же ресурсов. Вы можете найти неплохую статью (и более полный список) здесь: Щелкните
Это зависит от того, что должен содержать файл
. Если он предназначен для содержания разделенного IFS списка глобусов оболочки, например (при условии, что значение по умолчанию $IFS
):
/var/log/*.log /var/adm/*~
/some/dir/*.txt
Тогда для i в $(cat file)
будет путь. Именно это и делает этот $(cat file)
без кавычек: примените оператор split+glob к выходным данным cat file
, лишенным завершающих символов новой строки. Таким образом, он будет перебирать каждое имя файла, полученное в результате расширения этих глобусов (за исключением случаев, когда глобусы не соответствуют ни одному файлу, где это оставило бы глобус там, но нерасширенным).
Если вы хотите перебрать каждую строку с разделителями file
, вы должны сделать:
while IFS= read -r line <&3; do
{
something with "$line"
} 3<&-
done 3< file
С помощью цикла for
вы можете перебрать каждую непустую строку с помощью :
IFS=' ' # split on newline only (actually sequences of newlines and # ignoring leading and trailing ones as newline is a # IFS whitespace character) set -o noglob # disable the glob part of the split+glob operator: for line in $(cat file); do something with "$line" done
Однако a:
while read line; do
something with "$line"
done < file
Имеет мало смысла. Это чтение содержимого файла
очень запутанным способом, где символы $IFS
и обратные косые черты обрабатываются особым образом.
В любом случае, ARG_MAX ограничивает текст, на который вы цитируете, относится к системному вызову execve()
(на совокупный размер аргументов и переменных среды), поэтому применяется только к случаям где команда в файловой системе выполняется с, возможно, очень длинным расширением оператора split+glob, примененного к подстановке команды (этот текст вводит в заблуждение и неверен в нескольких учетных записях).
Это применимо, например, в:
cat -- $(cat file) # with shell implementations where cat is not builtin
Но не в:
for i in $(cat file)
где нет системного вызова execve()
.
Сравните:
bash-4.4$ echo '/*/*/*/*' > file
bash-4.4$ true $(cat file)
bash-4.4$ n=0; for f in $(cat file); do ((n++)); done; echo "$n"
523696
bash-4.4$ /bin/true $(cat file)
bash: /bin/true: Argument list too long
Это нормально со встроенной командой bash
's true
или с циклом for
, но не при выполнении /bin/ правда
. Обратите внимание, что файл
имеет размер всего 9 байт, но расширение $(cat file)
составляет несколько мегабайт, потому что /*/*/*/*
glob расширяется оболочкой.
Дополнительная литература:
while
Циклы могут быть проблематичными, в первую очередь из-за того, что они используют стандартный ввод по умолчанию (следовательно,ssh -n
)поэтому, если вам нужен стандартный ввод для чего-то другого, while
цикл не будет работать
$ find. -name "*.pm" | while read f; do aspell check $f; done
$
ничего не делает, так как aspell
хочет, чтобы терминал был занят списком имен модулей perl; цикл for
более подходит (при условии, что имена файлов не будут разделены правилами разделения слов POSIX):
$ for f in $(find. -name \*.pm); do aspell check $f; done
...
, так как он не использует стандартный ввод, как while
по умолчанию.
Кроме того, while
подвержен скрытой потере данных (, а for
ведет себя по-разному для одного и того же ввода):
$ echo -n mmm silent data loss | while read line; do echo $line; done
$ for i in $(echo -n mmm silent data loss); do echo $i; done
mmm
silent
data
loss
$
Таким образом, можно привести аргументы, что while
опасен и не должен использоваться, в зависимости от контекста.