xargs 및 vi - "입력이 터미널에서 나오지 않습니다."

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을 검색했지만 운이 없었습니다.

답변1

이 질문은 이전에 질문되었습니다.뿌리법정.

이 질문에 대한 @grawity의 답변을 인용하면 다음과 같습니다.

xargs를 통해 프로그램을 호출하면 프로그램의 stdin(표준 입력)이 /dev/null을 가리킵니다. (xargs는 원시 표준 입력에 대해 모르기 때문에 차선책만 수행할 수 있습니다.)

Vim은 표준 입력이 제어 터미널과 동일할 것으로 예상하고 표준 입력에서 직접 다양한 터미널 관련 ioctl을 수행합니다. /dev/null(또는 tty가 아닌 파일 설명자)에서 수행되면 이러한 ioctl은 의미가 없으며 자동으로 무시되는 ENOTTY를 반환합니다.

최신 버전의 OS X/macOS/BSD 및 GNU findutils xargs(다음으로 시작)v4.6.0-o) 이 정확한 시나리오를 해결하는 옵션이 있습니다 .

macOS/BSD 매뉴얼 페이지에서:

-o 명령을 실행하기 전에 하위 프로세스에서 /dev/tty로 stdin을 다시 엽니다. 이는 xargs가 대화형 응용 프로그램을 실행하도록 하려는 경우 유용합니다.

따라서 macOS에서는 다음 명령을 사용할 수 있습니다.

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

이전 버전의 GNU 사용을 고집한다면 xargs다음 명령이 작동합니다. (해당 문자열을 포함해야 합니다. dummy그렇지 않으면 첫 번째 파일이 삭제됩니다.)

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

위의 해결책은 정중합니다Jaime McGuigan이 말하는 "파워 유저". 향후 방문자가 사이트에서 이 오류를 검색할 수 있도록 여기에 추가하세요.

답변2

vi $(locate php.ini)

참고: 파일 경로에 공백, 탭, 줄 바꿈(기본값은 $IFS) 또는 glob 문자가 포함되어 있지만 기능적으로는 명령과 유사한 경우 문제가 발생합니다( xargs따옴표와 백슬래시를 특수 대시 문자로 처리하지만 처리하지 않음). ) 하지만 그렇게 하지 않습니다).
다음 버전에서는 공백, 탭 및 전역 문자를 올바르게 처리하지만 약간 복잡합니다.(파일 이름에 줄 바꿈이 있으면 여전히 깨집니다)

(IFS=$'\n'; set -o noglob; vi $(locate php.ini))

설명하다:

무슨 일이 일어나는가는 프로그램이 파일 디스크립터를 생성한 프로세스로부터 파일 디스크립터를 상속받는다는 것입니다. xargsSTDIN은 STDOUT에 연결되어 있으므로 locate원래 viSTDIN이 어디에 있는지 알 수 없습니다.

답변3

GNU findutils와 프로세스 교체를 지원하는 셸(ksh, zsh, bash)을 사용하면 다음을 수행할 수 있습니다.

xargs -r0a <(locate -0 php.ini) vi

-a filename아이디어는 stdin 대신에 파일 목록을 전달하는 것입니다. 사용하면 -0파일 이름에 포함된 문자 또는 비문자에 관계없이 올바르게 작동합니다.

이를 통해 zsh다음을 수행할 수 있습니다.

vi ${(0)"$(locate -0 php.ini)"}

( 0NUL에서 분할된 매개변수 확장 플래그는 어디에 있습니까?)

그러나 파일을 찾을 수 없는 경우에도 xargs -r인수 없이 실행할 수 있다는 점에 유의하세요.vi

답변4

동일한 편집기에서 여러 php.ini를 편집하시겠습니까?

노력하다: vim -o $(locate php.ini)

관련 정보