Xargs с командой, что открытый редактор оставляет оболочку в странном состоянии
Я попытался сделать псевдоним для выполнения нескольких различных проектов git. Я попробовал что-то вроде
cat projectPaths | \
xargs -I project git --git-dir=project/.git --work-tree=project commit -a
где projectPaths - это файл, содержащий пути ко всем проектам, которые я хочу совершить. Похоже, что это работает по большей части, запуская vi последовательно для каждого проекта, чтобы я мог написать для него сообщение commit. Однако я получаю сообщение:
"Vim: Предупреждение: вход не от терминала"
а потом мой терминал странный: он не отображает текст, который я печатаю, и, похоже, не выводит никаких строк перевода. Когда я вхожу в "reset", все в порядке, но я явно делаю что-то неправильно.
Есть ли способ получить такое же поведение, не запуская мою оболочку?
Спасибо!
Ответы
Ответ 1
Проблема заключается в том, что, поскольку вы используете xargs (и, следовательно, git и, следовательно, vim) в конвейере, его stdin берется из вывода cat projectPaths
, а не терминала; это путает vim. К счастью, решение прост: добавьте флаг -o
в xargs, и он запустит git (и, следовательно, vim) с помощью ввода /dev/tty вместо собственного stdin.
Ответ 2
Используя более простой пример
ls *.h | xargs vim
вы можете сделать это, чтобы исправить проблему:
vim $( ls *.h | xargs )
или
vim `ls *.h | xargs`
оба из этих примеров являются заменой команды. Второй пример с backticks устарел, поэтому вы должны использовать первый пример. Команды выполняются в подоболочке, и их данные stdout заменяются. Подробнее здесь.
если вы используете его по-старому и хотите, чтобы ваш терминал снова себя вел, вы можете использовать команду reset
.
Ответ 3
Страница man для GNU xargs
показывает аналогичную команду для emacs:
xargs sh -c 'emacs "[email protected]" < /dev/tty' emacs
и говорит следующее:
Launches the minimum number of copies of Emacs needed, one after the
other, to edit the files listed on xargs' standard input. This example
achieves the same effect as BSD -o option, but in a more flexible and
portable way.
Еще одна вещь, которую следует попробовать использовать -a
вместо cat
:
xargs -a projectPaths -I project git --git-dir=project/.git --work-tree=project commit -a
или некоторая комбинация двух.
Ответ 4
Если у вас установлен GNU Parallel http://www.gnu.org/software/parallel/, вы должны это сделать:
cat projectPaths |
parallel -uj1 git --git-dir={}/.git --work-tree={} commit -a
В целом это тоже работает:
cat filelist | parallel -Xuj1 $EDITOR
если вы хотите редактировать несколько файлов за раз (и вы установили $EDITOR в свой любимый редактор).
-o
для xargs
(как упоминалось выше) работает только для некоторых версий xargs
(особенно это не работает для GNU xargs).
Смотрите видеоролик, чтобы узнать больше о GNU Parallel http://www.youtube.com/watch?v=OpaiGYxkSuQ
Ответ 5
Интересно! Я также вижу то же самое поведение на Mac, делая что-то так же просто, как:
ls *.h | xargs vim
По-видимому, это проблема с vim:
http://talideon.com/weblog/2007/03/xargs-vim.cfm