를 vim
통해 호출 할 때 다음 find | xargs
과 같이하십시오.
find . -name "*.txt" | xargs vim
당신은에 대한 경고를받을
Input is not from a terminal
그리고 이후에 거의 고장난 터미널이 있습니다. 왜 그런 겁니까?
grep -l .. | xargs vim
경고를 생성하는 이유는 무엇입니까? 유닉스 SE에서
를 vim
통해 호출 할 때 다음 find | xargs
과 같이하십시오.
find . -name "*.txt" | xargs vim
당신은에 대한 경고를받을
Input is not from a terminal
그리고 이후에 거의 고장난 터미널이 있습니다. 왜 그런 겁니까?
grep -l .. | xargs vim
경고를 생성하는 이유는 무엇입니까? 유닉스 SE에서
답변:
를 통해 프로그램을 호출 xargs
하면 프로그램의 표준 입력 (표준 입력)이을 가리 킵니다 /dev/null
. (xargs는 원래 stdin을 알지 못하므로 다음으로 최선을 다합니다.)
$ 진실 | xargs filan -s 0 chrdev / dev / null 1 tty / dev / pts / 1 2 tty / dev / pts / 1 $ 진실 | xargs ls -l / dev / fd /
Vim은 stdin이 제어 터미널과 동일 할 것으로 기대하고 stdin에서 다양한 터미널 관련 ioctl을 직접 수행합니다. 에 완료되면 /dev/null
(또는 비 청각 장애 파일 기술자), 그 ioctl의 의미가 있으며 자동으로 무시됩니다 ENOTTY를 반환합니다.
더 구체적인 원인에 대한 나의 추측 : 시작할 때 Vim은 이전 터미널 설정을 읽고 기억하고 종료 할 때 다시 복원합니다. 이 상황에서 tty가 아닌 fd (파일 설명자)에 대해 "이전 설정"이 요청되면 Vim은 모든 값을 비우고 모든 옵션을 사용할 수 없게 설정하고 터미널에 동일하게 설정합니다.
을 실행 vim < /dev/null
하고 종료 한 다음 실행 stty
하면이 모든 것을 볼 수 있습니다 <undef>
. Linux에서 실행은 stty sane
(는 있지만 다시 터미널 사용할 수를 만들 것입니다 것 같은 옵션을 잃었을 iutf8
가능성이 나중에 사소한 불만의 원인).
터미널 제어를 위해 열 수는/dev/tty
있지만 Vim에서는이 버그를 고려할 수 는 없습니다. (시작하는 동안 어느 시점에서 Vim은 stderr을 stdin으로 복제하여 쓰기를 위해 열린 fd에서 입력 명령을 읽을 수는 있지만 충분히 일찍 수행되지는 않습니다.)
stty sane
reset
대신 대신 사용 stty sane
하고 그 후에 잘 작동합니다.
(grawity의 설명,에 이어 xargs
지적 stdin
에 /dev/null
.)
솔루션 이 문제는 추가하는 것입니다 -o
에 매개 변수를 xargs
. 보낸 사람 man xargs
:
-o
/dev/tty
명령을 실행하기 전에 하위 프로세스에서와 같이 stdin을 다시여십시오 .xargs
대화식 응용 프로그램을 실행 하려는 경우에 유용합니다 .
따라서 다음 코드 줄이 작동합니다.
검색 . 이름 "* .txt"| xargs -o vim
GNU xargs는 2017 년 일부 릴리스 (긴 옵션 이름 --open-tty
) 이후이 확장을 지원합니다 .
이전 버전 또는 다른 버전의 xargs의 경우 명시 적으로 전달 /dev/tty
하여 문제를 해결할 수 있습니다.
find . -name "*.txt" | xargs bash -c '</dev/tty vim "$@"' ignoreme
( ignoreme
$ 0을 차지하므로 $ @는 xargs의 모든 인수입니다.)
$@
인수를 올바르게 번역하지 않는 것 같습니다.
function vimin () { xargs sh -c 'vim "$@" < /dev/tty' vim; }
ignoreme
문자열을 참조 vi.stackexchange.com/a/17813을
The -J, -o, -P and -R options are non-standard FreeBSD extensions which may not be available on other operating systems.
(homebrew (GNU)에서 xargs를 설치했기 때문에 macOS에서는 사용할 수 없었습니다)
가장 쉬운 방법 :
vim $(find . -name "*foo*")
xargs로 파이프하는 대신 찾기에 -exec 옵션을 사용하면 제대로 작동합니다.
find . -type f -name filename.txt -exec vi {} +
+
(대신 "보통"의 \;
에 발견 된 모든 파일을 얻을) 하나 개의 옵션은 내가 - 빔 세션 계속 잊고. 물론 그렇습니다. 나는 vim $(find ...)
단순히 습관에서 벗어납니다. 그러나 실제로 파이프 작업으로 인해 터미널이 망가지는 이유를 묻고 있었으며 Grawity는 설명을 통해 그 사실을 파악했습니다.
대신 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
vim $(find . -name "*.txt")
더 간단하고 모든 파일을 한 번에 열 수 있습니다.
find | xargs
와 $(find)
파일 이름에 공백이 큰 문제가됩니다.
$IFS
, -print0
및 것들을 다루기 시작한 다음 원샷 명령 줄 솔루션의 영역을 떠나 스크립트를 생각해 내야 할 시점에 도달했습니다 ... 파일 이름의 공백이 권장되지 않는 이유가 있습니다. .
아마도 최고는 아니지만 여기서 내가 사용하는 스크립트 ( vim-open
) :
#!/usr/bin/env ruby
require 'shellwords'
inputs = (ARGV + (STDIN.tty? ? [] : STDIN.to_a)).map(&:strip)
exec("</dev/tty vim #{inputs.flatten.shelljoin}")
로 작동 vim-open a b c
하고 ls | vim-open
, 예를 들어
find
하거나 전혀 사용하지 않을 수 있습니다xargs
. 인수없이 vim을 연 다음:args **/*.txt<CR>
편집기 내부에서 vim의 인수를 설정하기 위해 실행 합니다.