Как Ulrich упомянул в своем комментарии, которым причина состоит в том, что многобайтовые символы всегда считаются частью слова. Они не должны быть указаны в iskeyword
. Заключить справку в кавычки :h iskeyword
который указывает на :h isfname
:
Многобайтовые символы 256 и выше всегда включаются, только символы, до 255 указаны с этой опцией. Для UTF-8 символы 0xa0 к 0xff включены также.
Директива for f in $(find .)
разделяет список элементов для итерации пространством. В современной оболочке, как zsh, могли использоваться флаги расширения.
for f in "${(@f)$(find .)}" ; do echo "$f" ; done
Пребывание с bash
, мы можем работать вокруг этого, любят упомянутый в другом вопросе, изменяющем входной разделитель, символ раньше разделял элементы, временно при присвоении результатов find
к переменной. Отключение бахвалящийся в течение времени, будучи предотвращает расширение подстановочных символов, такой как *
в них.
set -f # Disable globbing.
IFS=$(echo -e '\0') files=( $(find . -print0) ) # Read newline separated files into an array.
for f in ${files[@]}; do echo $f; done
set +f # Reenable globbing.
Но это просто смещает проблему, теперь она не будет работать, когда новая строка будет в любом имени файла. Существует всего одна вещь, запрещенная в, вероятно, всех файловых системах, который является нулевым символом. Но переменные в ударе не могут содержать это, таким образом, мы не можем присвоить его IFS
.
С другой стороны, xargs может использоваться для передачи путей от find
к другой программе. Используя -print0
команда к find
и -0
переключатель к xargs
, они используют нулевой символ в качестве разделителя. Добавление -n1
к xargs
назовите дескрипторы одним именем файла за один раз.
find . -print0 | xargs -0 -n1 echo
Вы дважды заключенный в кавычки подстановка переменных в аргументе echo
, но не замена команды в итеративном списке for
цикл. Это - то, где разделение на пробеле и другой злобности происходит.
Нет никакого полностью надежного способа проанализировать вывод find
, потому что Вы не можете сказать, является ли новая строка частью имени файла или разделителя.
Если можно предположить, что имена файлов не содержат новые строки, то можно расположить разделить вывод find
путем ограничения символов разделителя полей только символом новой строки (для защиты пробелов и вкладок) и выключения globbing (для защиты \[?*
).
IFS='
'; set +f
for f in $(find .); do
unset IFS; set +f
echo "$f"
done
unset IFS; set +f
Существуют лучшие способы сделать это, все же. Самый легкий способ использовать find
надежно должен заставить его выполнить команду, вместо того, чтобы анализировать ее вывод. Это также потенциально быстрее, так как файлы имеют хороший шанс того, чтобы быть обработанным, в то время как их метаданные находятся все еще в кэше.
find . -exec echo {} \;
При необходимости в команде оболочки вызовите оболочку явно. Остерегайтесь заключения в кавычки — передают имя файла как аргумент оболочке, не пытайтесь интерполировать его в команде оболочки.
find . -exec sh -c 'echo "$0"' {} \;
Вместо того, чтобы вызвать один экземпляр оболочки на файл, можно сгруппировать вызовы оболочки и цикл по набору файлов. find
команда делает группирование и удостоверяется для не осмотра через предел длины командной строки. Не забывайте передавать фиктивный аргумент как $0
так, чтобы файлы были $1
и так далее.
find . -exec sh -c 'for x; do echo "$x"; done' _ {} +
При использовании ksh93, удара или zsh, можно использовать их рекурсивное globbing средство: **/PATTERN
поиски подстановочного шаблона в каталоге и его подкаталогах рекурсивно. В ksh93 необходимо работать set -o globstar
сначала. В ударе необходимо работать shopt -s globstar
во-первых, и остерегайтесь этого **
также рекурсивно вызывает внутренние символьные ссылки на каталоги.
for f in **/*; do
echo "$f"
done
Zsh также имеет спецификаторы шарика, которые включают в категорию большую часть использования find
. Другие оболочки не имеют такой вещи.
IFS='\n'
вbash
? Вы уверены, что это делает то, что Вы хотите? – manatwork 05.12.2013, 15:14IFS
к двум символам: “\\” и “n”. Так безотносительноfind
выводы будут разделены на любом из тех двух символов. pastebin.com/kj8PsrKw – manatwork 05.12.2013, 15:27$'\n'
это действительно оценивает к символу новой строки. pastebin.com/3NGSB1n4 – XZS 05.12.2013, 16:34for f in "$(find .)"
, в любой оболочке, выполняет тело цикла точно однажды. В Вашем решении для удара Вы избежали отключать globbing, и необходимо отметить, что это порывает с именами файлов, содержащими новые строки. – Gilles 'SO- stop being evil' 06.12.2013, 01:07