Как мне выполнить итерацию по всем строкам, выводимым командой в zsh?

#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!)