У меня есть около 10 php.ini
файлов в моей системе, расположенных повсюду, и я хотел быстро просмотреть их. Я попробовал эту команду:
locate php.ini | xargs vi
Но vi
предупреждает меня, Input is not from a terminal
и затем консоль начинает становиться действительно странной - после чего мне нужно нажать, :q!
чтобы выйти, vi
а затем отключиться от сеанса ssh и повторно подключиться, чтобы консоль снова работала нормально.
Я думаю, что я вроде понимаю, что здесь происходит - в основном, команда не завершилась при vi
запуске, поэтому, возможно, команда не завершила и vi
не думает, что терминал находится в нормальном режиме.
Я понятия не имею, как это исправить. Я искал Google, а также unix.stackexchange.com с неудачей.
reset
для сброса вашего терминала, когда он облажался (вам не нужно отключаться от сеанса SSH).Ответы:
Примечание: это будет иметь проблемы, если пути к вашим файлам имеют пробелы, но это функционально эквивалентно вашей команде.
Следующая версия будет корректно обрабатывать пробелы, но она немного сложнее (хотя новые строки в именах файлов все равно будут ее разбивать)
Объяснение:
Происходит то, что программы наследуют свои файловые дескрипторы от процесса, который их породил.
xargs
его STDIN подключен к STDOUTlocate
, такvi
что понятия не имеет, что на самом деле представляет собой оригинальный STDIN.источник
xargs
поскольку это нельзя было сделать напрямую с помощью оболочки (илиfind
). Однако я могу вспомнить случаи, когда это было бы лучшим решением. Так что, пока вы понимаете, чтоxargs
делаете, как он разделяет аргументы, как запускает программу и т. Д., И правильно ли используете ее, я бы сказал: «П... | awk '{print $3}' | xargs | sed -e 's/ /+/g' | bc
(сложить все значения поля 3). или с помощьюsed -e 's/ /|/g'
построения регулярного выражения. и да, как и любой инструмент, вам нужно знать, как его использовать и каковы его ограничения и предостережения.vi $(...)
Подход также имеет проблемы с групповыми символами в других , чем снарядахzsh
.xargs
подходе к проблеме пробелов имена файлов с одинарными, двойными и обратными слешами также являются проблемой.Этот вопрос ранее задавался на форуме Super User .
Цитирую ответ @ grawity на этот вопрос:
Это упомянуто на страницах руководства для xarg. Из OSX / BSD:
Следовательно, в OSX вы можете использовать следующую команду:
Пока нет прямого переключения на версию GNU, эта команда будет работать. (Обязательно включите
dummy
строку, в противном случае будет удален первый файл.)Вышеуказанные решения предоставлены Jaime McGuigan на SuperUser . Добавление их сюда для любых будущих посетителей, ищущих сайт по данной ошибке.
источник
xargs sh -c 'emacs "$@" < /dev/tty' emacs
более гибкую и переносимую альтернативу (хотя для GNU довольно забавно предпочитать переносимость функциям :).С GNU
findutils
и оболочкой с поддержкой подстановки процессов (ksh, zsh, bash) вы можете сделать:Идея состоит в том, чтобы передать список файлов,
-a filename
а не через стандартный ввод. Использование-0
гарантирует, что оно работает независимо от того, какие символы или не символы могут содержать имена файлов.С помощью
zsh
вы можете сделать:(где
0
флаг расширения параметра для разделения на NUL).Однако обратите внимание, что в противоположность
xargs -r
этому все еще работаетvi
без аргумента, если файл не найден.источник
Редактировать несколько php.ini в одном редакторе?
Пытаться:
vim -o $(locate php.ini)
источник
Эта ошибка возникает, когда vim вызывается и подключается к выходу предыдущего конвейера, а не к терминалу и получает неожиданный ввод (например, NUL). То же самое происходит при запуске:,
vim < /dev/null
так чтоreset
команда в этом случае помогает. Это хорошо объясняется благодарностью суперпользователя .В Unix / OSX вы можете использовать
xargs
с-o
параметром, например:В Linux попробуйте следующий обходной путь:
В качестве альтернативы используйте GNU
parallel
вместоxargs
принудительного распределения tty, например:Примечание:
parallel
в Unix / OSX не будет работать, так как он имеет разные параметры и не поддерживает tty.Многие другие популярные команды также предоставляют псевдо-tty распределение (например,
-t
вssh
), поэтому обратитесь за помощью.В качестве альтернативы используйте
find
для передачи имен файлов для редактирования, так что не нужноxargs
, просто используйте-exec
, например:источник
IFS
Взлом @ Патрика необходим только для таких глупых оболочек, какbash
иzsh
.fish
разбивает строку на новые строки по умолчанию.И Бог поможет нам всем, если у одного из нас действительно есть файл с новой строкой в его имени. После 17 лет использования Linux я не видел его ни разу. Я бы не стал поддерживать имена файлов с символами новой строки в них для сценариев, которые должны работать несмотря ни на что, но такие сценарии, вероятно, не запускают vim в интерактивном режиме.
источник
zsh
по умолчанию разделяется на SPC, TAB, NL и NUL. По сравнению с тем, с чем он неbash
справляется, выполняет глобализацию результата, поэтому подстановочные знаки в именах файлов не являются проблемой. Вzsh
, вы бы сделалиIFS=$'\0'; vi $(locate -0 php.ini)
или, как я показал в моем ответеvi ${(0)"$(locate -0 php.ini)"}
для явного оператора расщепления. Также обратите внимание, что tcsh'svi "`locate php.ini`"
$ f='not there'<ret>$ ls $f<ret>
но это не так: lsecho not there
. ОК, похоже, мне нужно обновить это немного.ls "$(echo test; echo other test)"
. Только рыба делает правильные вещи.$IFS
помощью явных операторов (f
и0
флагов расширения параметров). Для произвольных имен файлов разделение по слову или разделение по строке одинаково неправильно , вам нужно разделить по NUL или проанализировать некоторую кодировку, чегоfish
не может быть. Воzsh
, этоIFS=$'\0'; ls -ld -- $(printf '%s\0' "$file1" "$file2")
илиls -ld -- ${(0)"$(printf '%s\0' "$file1" "$file2")"}
Быстрый способ сделать это, если вы не можете гарантировать ни один из файловых путей содержат SPC, TAB, NL,
*
,?
,[
символы (также\
и{...}
в некоторых оболочках) является использование бэк-тиков (AKA серьезных акцентов) , чтобы выполнить команду до другая команда работает.Например
Команда, содержащаяся в обратных тиках, будет выполнена первой. Вывод содержащейся команды затем выполняется командой, указанной перед обратными галочками.
Например, в приведенной выше строке
find / -type f -name 'php.ini'
команда сначала выполнится, отправит вывод, а затемvi
будет выполнена с результатом split + glob, примененным к этому выводу.источник
$(find ...)
вместо этого.vi
помощью этого метода. Вполне возможно, что он может разбиться на новые строки или пробелы, в зависимости от того, какvi
читает и выполняет вывод.