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 с плохой удачей.

  • xargs на OSX: незаконный вариант -
  • Найти изображения по размеру: find / file / awk
  • Найдите полный путь и имя файла под каталогом, затем перейдите в исполняемый файл в качестве аргументов
  • Удаление некоторых из самых больших файлов в каталоге
  • Unix: вопрос о xargs
  • цикл xargs с переменной ввода для использования в команде с несколькими командами
  • Список файлов с меткой времени с эпохи
  • Где «xargs» добавляет опцию из STDIN?
  • 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 {} + 
    Linux и Unix - лучшая ОС в мире.