Ответ BLayer правильный, но чтобы разобрать, что здесь происходит на самом деле (, игнорируя опечатку отсутствующего -name
первичного):
#!/bin/bash
while IFS= read -r -d '' file; do
files+=$file
done < <(find -type f -name '*.c' -print0)
echo "${files[@]}"
В оболочке, запущенной подстановкой процесса (<(...)
), следующая команда анализируется bash:
find -type f -name '*.c' -print0
Поскольку glob *.c
заключен в кавычки, bash не расширяет его . Однако одинарные кавычки удаляются. Таким образом, когда процесс find
запускается, он видит список своих аргументов:
-type
f
-name
*.c
-print0
Обратите внимание, что эти аргументы разделены нулевыми байтами , а не пробелами или символами новой строки. Это на уровне C, а не на уровне оболочки. Это связано с тем, как программы выполняются с использованием execve()
в C.
Теперь для контраста в следующем фрагменте:
#!/bin/bash
find_args="-type f -name '*.c' -print0"
while IFS= read -r -d '' file; do
files+=$file
done < <(find $find_args)
echo "${files[@]}"
Значение переменной find_args
устанавливается равным:
-type f -name '*.c' -print0
(Двойные кавычки не являются частью значения, в отличие от одинарных кавычек .)
При выполнении команды find $find_args
в соответствии с man bash
токен $find_args
подвергается расширению параметра , за которым следует разбиение на слова , за которым следует расширение имени пути (также известное как расширение шара ).
После расширения параметра у вас есть -type f -name '*.c' -print0
. Обратите внимание, что это после удаления кавычки . Таким образом, одинарные кавычки не будут удалены.
После разделения слов у вас есть следующие отдельные слова:
-type
f
-name
'*.c'
-print0
Затем идет расширение имени пути. Конечно, '*.c'
вряд ли будет соответствовать чему-либо, поскольку вы обычно не ставите одинарные кавычки в именах файлов, поэтому результатом будет , скорее всего, будет то, что '*.c'
будет передано как литеральный шаблон в find
, поэтому первичный -name
не будет работать со всеми файлами. (Успешно, только если есть файл, имя которого начинается с одинарной кавычки и заканчивается тремя символами.c'
)
Редактировать :Собственно, если есть такой файл,glob '*.c'
будет расширяться, чтобы соответствовать этому файлу и любым другим таким файлам, а затем расширение [фактическое имя файла] будет передано в find
как шаблон . Таким образом, будет ли когда-либо достигнут -print0
первичный файл или нет, зависит от (a )того, существует ли только одно такое имя файла, и (b )от того, является ли это имя файла, интерпретируемый как шар, соответствует самому себе.
Примеры:
Если вы запустите touch "'something.c'"
, то глобус '*.c'
расширится до 'something.c'
, а затем первичный find
-name 'something.c'
также будет соответствовать этому файлу, и он будет напечатан.
Если вы запустите touch "'namewithcharset[a].c'"
, глобус '*.c'
будет расширен до этого оболочкой, но find
первичный -name 'namewithcharset[a].c'
будет не соответствовать самому себе — он будет соответствовать только 'namewithcharseta.c'
, которого не существует, поэтому -print0
не будет достигнуто.
Если вы запустите touch "'x.c'" "'y.c'"
, глобус '*.c'
расширится до обоих имен файлов , что приведет к выводу ошибки из find
, поскольку 'y.c'
не является допустимым первичным (и не может быть, так как не начинается с дефиса ).
Если установлена опция nullglob
, вы получите другое поведение.
См. также:
Я не знаю, какую версию netcat вы используете, но в моей нет параметра -c
. Тем не менее, tail -F /var/log/changes.log | nc 127.0.0.1 1234
работает для меня.