При вызове vim
через find | xargs
, вот так:
find . -name "*.txt" | xargs vim
вы получаете предупреждение о
Input is not from a terminal
и терминал с в значительной степени сломанным поведением впоследствии. Это почему?
Исходя из ответа Гравити , xargs
указывает на стандартный stdin
/dev/null
От OSX/BSD man xargs
-o Reopen stdin as /dev/tty in the child process before executing the command. This is useful if you want xargs to run an interactive application.
Таким образом, следующая строка кода должна работать для вас:
find . -name "*.txt" | xargs -o vim
Для GNU man xargs
флаг отсутствует, но мы можем явно передать /dev /tty для решения проблемы:
find . -name "*.txt" | xargs bash -c '</dev/tty vim "$@"' ignoreme
ignoreme должен взять $ 0, так что $ @ - это все аргументы из xargs
Когда вы вызываете программу через xargs
, стандартный ввод программы указывает на /dev/null
. (Так как xargs не знает оригинальный stdin, он делает следующую лучшую вещь.)
$ true | xargs filan -s 0 chrdev /dev/null 1 tty /dev/pts/1 2 tty /dev/pts/1 $ true | xargs ls -l /dev/fd/
Vim ожидает, что его stdin будет таким же, как его управляющий терминал, и напрямую выполняет различные связанные с терминалом ioctl на stdin. Когда это делается в /dev/null
(или любом не-tty файловом дескрипторе), эти ioctl не имеют смысла и возвращают ENOTTY, что молча игнорируется.
Я предполагаю более конкретную причину: при запуске Vim считывает и запоминает старые настройки терминала и восстанавливает их при выходе. В нашей ситуации, когда "старые настройки" запрашиваются для не-tty fd (дескриптор файла), Vim получает все значения пустыми и все опции отключены и небрежно устанавливает их для вашего терминала.
Вы можете увидеть это, запустив vim < /dev/null
, выйдя из него, затем запустив stty
, что выдаст целую партию <undef>
. В Linux работает stty sane
сделает терминал пригодного для использования (хотя он потерял такие варианты , как iutf8
возможно , вызывая незначительный раздражали позже).
Вы можете считать это ошибкой в Vim, поскольку он может открывать /dev/tty
для управления терминалом, но не открывает. (В какой-то момент во время запуска Vim дублирует свой stderr на stdin, что позволяет ему читать ваши входные команды - с открытого для записи fd - но даже это делается недостаточно рано.)
Самый простой способ:
vim $(find . -name "*foo*")
Все должно работать нормально, если вы используете опцию -exec в find, а не отправляете в xargs. Например
$ find . -type f -name filename.txt -exec vi {} +
Вместо этого используйте GNU Parallel:
find . -name "*.txt" | parallel -j1 --tty vim
Или, если вы хотите открыть все файлы за один раз:
find . -name "*.txt" | parallel -Xj1 --tty vim
Он даже правильно работает с именами файлов, такими как:
My brother's 12" records.txt
Посмотрите вступительное видео, чтобы узнать больше: http://www.youtube.com/watch?v=OpaiGYxkSuQ