xargs и vi – «Вход не от терминала»

У меня около 10 файлов php.ini в моей системе, расположенных повсюду, и я хотел быстро просмотреть их. Я пробовал эту команду:

 locate php.ini | xargs vi 

Но vi предупреждает меня. Input is not from a terminal а затем консоль начинает становиться действительно странным – после чего мне нужно нажать :q! чтобы выйти из vi а затем отключиться от сеанса ssh и снова подключиться, чтобы консоль вела себя нормально снова.

Я думаю, что я разбираюсь в том, что здесь происходит – в основном команда не закончилась, когда началась vi поэтому команда, возможно, не закончилась, и vi не считает, что терминал находится в нормальном режиме.

Я понятия не имею, как это исправить. Я искал Google, а также unix.stackexchange.com с плохой удачей.

5 Solutions collect form web for “xargs и vi – «Вход не от терминала»”

Я ненавижу xargs , мне очень жаль, что он просто не умрет 🙂

 vi $(locate php.ini) 

Примечание. У этого будут проблемы, если ваши пути к файлам имеют пробелы, но функционально эквивалентны вашей команде.
Эта следующая версия будет правильно обрабатывать пробелы, но немного сложнее ( новые строки в именах файлов все равно будут разбиты)

 (IFS=$'\n'; vi $(locate php.ini)) 

Объяснение:

Что происходит, так это то, что программы наследуют свои файловые дескрипторы из процесса, который их породил. xargs имеет свой STDIN, подключенный к STDOUT для locate , поэтому vi не знает, что такое оригинальный STDIN.

Ранее этот вопрос задавали на форуме Super User .

Цитата из ответа @ grawity на этот вопрос:

Когда вы вызываете программу через xargs, stdin (стандартный ввод) программы указывает на / dev / null. (Поскольку xargs не знает оригинальный stdin, он делает следующее лучшее.)

Vim ожидает, что его stdin будет таким же, как и его управляющий терминал, и напрямую выполняет различные связанные с терминалом ioctl на stdin. Когда это делается в / dev / null (или любом дескрипторе файла не-tty), эти ioctls бессмысленны и возвращают ENOTTY, который бесшумно игнорируется.

Это упоминается на страницах руководства для xarg. Из OSX / BSD:

-o Повторно открыть stdin как / dev / tty в дочернем процессе перед выполнением команды. Это полезно, если вы хотите, чтобы xargs запускали интерактивное приложение.

Следовательно, в OSX вы можете использовать следующую команду:

 find . -name "php.ini" | xargs -o vim 

Хотя в GNU-версии нет прямого переключения, эта команда должна работать:

 find . -name "php.ini" | xargs bash -c '</dev/tty vim "$@"' 

Вышеупомянутые решения – любезность Хайме МакГигана на SuperUser. Добавьте их сюда для будущих посетителей, которые ищут сайт для этой ошибки.

Быстрый способ сделать это – использовать back-ticks (aka grave accents) для выполнения команды перед запуском другой команды.

Например

 vi `find / -type f -name 'php.ini'` 

Сначала будет выполняться команда, содержащаяся в обратном тике. Затем вывод содержащейся команды выполняется командой, указанной перед обратными тиками.

Например, в строке выше команда find / -type f -name 'php.ini' выполнит сначала, отправит вывод, а затем будет vi на этом выходе.

Редактировать несколько php.ini в одном редакторе?

Попробуйте: vim -o $(locate php.ini)

Эта ошибка возникает, когда vim вызывается и подключается к выходу предыдущего конвейера, а не к терминалу, и получает разные неожиданные данные (например, NUL). То же самое происходит при запуске: vim < /dev/null , поэтому команда reset в этом случае помогает. Это объясняется грамотностью у суперпользователя .

В Unix / OSX вы можете использовать xargs с параметром -o , например:

 locate php.ini | xargs -o vim 

-o Повторно открыть stdin как / dev / tty в дочернем процессе перед выполнением команды. Это полезно, если вы хотите, чтобы xargs запускали интерактивное приложение.

В Linux попробуйте следующее обходное решение:

 locate php.ini | xargs -J% sh -c 'vim < /dev/tty $@' 

Альтернативно используйте GNU- parallel вместо xargs для принудительного распределения tty, например:

 locate php.ini | parallel -X --tty vi 

Примечание: parallel в Unix / OSX не будет работать, поскольку она имеет разные параметры и не поддерживает tty.

Многие другие популярные команды также предоставляют псевдо-tty-распределение (например, -t в ssh ), поэтому обратитесь за помощью.

В качестве альтернативы используйте find для передачи имен файлов для редактирования, поэтому не нужны xargs , просто используйте -exec , например:

 find /etc -name php.ini -exec vim {} + 
  • почему вывод xargs -n2 применяется к тому же количеству аргументов, различающихся по каналам или с клавиатуры?
  • вывод технологического процесса на команду split by line и whitespace
  • Получите дополнение к результату команды ls
  • Unix: вопрос о xargs
  • xargs не запрашивает после каждой строки
  • Содержимое выходного файла с grep вместе с именем каталога
  • Импортировать SQL-файлы с помощью xargs
  • xargs на OSX: незаконный вариант -
  • Как удалить файлы, отфильтрованные awk
  • Пропустить входной файл через трубу в качестве аргумента?
  • Как я могу создать файл, который я получил из stdin без xargs
  • Использовать xargs для перемещения файлов из каталога
  • Linux и Unix - лучшая ОС в мире.