#iteration #zsh #lines
#итерация #zsh #строки
Вопрос:
Как мне выполнить итерацию по всем строкам, выводимым командой с использованием zsh, без установки IFS?
Причина в том, что я хочу запустить команду для каждого файла, выводимого командой, и некоторые из этих файлов содержат пробелы.
Например, учитывая удаленный файл:
foo/bar baz/gamma
То есть один каталог ‘foo’, содержащий подкаталог ‘bar baz’, содержащий файл ‘gamma’.
Затем выполняется:
git ls-files --deleted | xargs ls
В этом файле будет указано, что он обрабатывается как два файла: ‘foo / bar’ и ‘/ baz / gamma’.
Мне нужно, чтобы это обрабатывалось как один файл: ‘foo / bar baz / gamma’.
Комментарии:
1. есть ли в вашей системе команда xargs?
2. @lunixboches: Да, это так, однако он по-прежнему не обрабатывает строки должным образом.
3.
git ls-files -z | xargs -0 ls
вместо пробелов будут использоваться разделители null ()
Ответ №1:
Если вы хотите запустить команду один раз для всех строк:
ls "${(@f)$(git ls-files --deleted)}"
f
Флаг расширения параметра означает разделение вывода команды на новые строки. Существует более общая форма (@s:||:)
для разделения на произвольную строку, например ||
. @
Флаг означает сохранение пустых записей. Несколько сбивает с толку, что все расширение должно быть заключено в двойные кавычки, чтобы избежать IFS
разделения при выводе команды подстановки, но это приведет к созданию отдельных слов для каждой записи.
Если вы хотите запускать команду для каждой строки по очереди, переносимая идиома не является особенно сложной:
git ls-filed --deleted | while IFS= read -r line; do ls $line; done
Если вы хотите запускать команду столько раз, сколько позволяет ограничение длины командной строки, используйте zargs .
autoload -U zargs
zargs -- "${(@f)$(git ls-files --deleted)}" -- ls
Комментарии:
1. Спасибо за это — здесь много полезной информации, но я думаю, что xargs все еще более эффективен, потому что он будет запускать одну команду для каждой группы файлов. (Что, если у меня так много файлов, которые не помещаются в список аргументов?)
2. @Arafangion
zargs
похожxargs
(запускает как можно меньше экземпляров при установке внутри ограничения длины командной строки), только с разумным интерфейсом.
Ответ №2:
Использование tr
и -0
параметр xargs
, предполагая, что строки не содержат 00
(NUL), что является справедливым предположением, поскольку NUL является одним из символов, которые не могут отображаться в именах файлов:
git ls-files --deleted | tr 'n' '00' | xargs -0 ls
это превращает строку: foo/bar baz/gamman
в foo/bar baz/gamma00
который xargs -0
знает, как обращаться
Комментарии:
1. Лучше не придумаешь, спасибо! (И это работает и в bash!)