IO 리디렉션 및 헤드 명령

IO 리디렉션 및 헤드 명령

오늘 저는 Cygwin bash 쉘에서 파일을 빠르게 편집하려고 하다가 .hgignore잘못된 줄을 추가했습니다. 이것이 최선의 접근 방식인지는 확실하지 않지만 head -1 .hgignore문제가 있는 줄을 삭제하는 방법을 빠르게 생각했습니다(이전에는 파일에 한 줄만 있었습니다). 물론, 실행되면 첫 번째 줄이 유일한 출력으로 제공됩니다.

그러나 출력을 리디렉션하고 rewrite file 을 사용하려고 하면 head -1 .hgignore > .hgignore파일이 비어 있습니다. 왜 이런 일이 발생합니까? 부착하려고 하면 head -1 .hgignore >> .hgignore올바르게 부착되지만 분명히 원하는 결과는 아닙니다. 이 경우 잘린 리디렉션이 작동하지 않는 이유는 무엇입니까?

답변1

내 생각엔 브루스가 대답할 것 같아여기서 무슨 일이 일어나고 있나요?하우징 배관 포함.

내가 가장 좋아하는 작은 유틸리티 중 하나 sponge더 많은 유틸리티. 대상 출력 파일을 열고 데이터를 쓰기 전에 사용 가능한 모든 입력을 "싱크"하여 이 문제를 해결합니다. 이를 통해 의도한 대로 정확하게 파이프라인을 작성할 수 있습니다.

$ head -1 .hgignore | sponge .hgignore

가난한 사람의 해결책은 출력을 임시 파일로 파이프한 다음 파이프가 완료된 후(예: 실행하는 다음 명령) 임시 파일을 원래 파일 위치로 다시 이동하는 것입니다.

$ head -1 .hgingore > .hgignore.tmp
$ mv .hgignore{.tmp,}

답변2

쉘이 다음과 같은 명령줄을 받으면: command > file.out쉘 자체는 이라는 파일을 엽니다(그리고 생성할 수도 있습니다) file.out. 쉘은 파일 설명자 0을 열려서 얻은 파일 설명자로 설정합니다. 이것이 I/O 리디렉션이 작동하는 방식입니다. 각 프로세스는 파일 설명자 0, 1, 2에 대해 알고 있습니다.

가장 어려운 부분은어떻게열려 있는 file.out. 대부분의 경우 file.out쓰기 위해 오프셋 0(즉, 잘라내기)에서 열기를 원하며 이것이 쉘이 수행하는 작업입니다. .hgignore를 자르고 쓰기 위해 열고 파일 설명자를 0으로 복사한 다음 exec를 실행합니다 head. 즉각적인 파일 손상.

Bash 쉘에서는 set noclobber다음을 수행하여 이 동작을 변경할 수 있습니다.

답변3

존재하다

head -n 1 file > file

filehead시작하기 전에 잘렸지만 작성하는 경우:

head -n 1 file 1<> file

file읽기-쓰기 모드에서는 열리지 않습니다 . 그러나 head쓰기가 완료되면 파일이 잘리지 않으므로 위 줄은 작동하지 않습니다( head첫 번째 줄 자체만 다시 작성되고 다른 줄은 변경되지 않은 채 유지됩니다).

그러나 head반환 후 fd아직 열려 있는 동안 다른 실행을 호출할 수 있습니다 truncate.

예를 들어:

{ head -n 1 file; perl -e 'truncate STDOUT, tell STDOUT'; } 1<> file

여기서 중요한 점은 truncate위 내용이 head파일의 첫 번째 줄 이후 fd 1로만 커서를 이동한다는 것입니다. 우리에게 필요하지 않은 첫 번째 줄을 다시 작성하지만, 거기에는 아무런 해가 없습니다.

POSIX 헤더를 사용하면 첫 번째 줄을 다시 작성하지 않고도 실제로 벗어날 수 있습니다.

{ head -n 1 > /dev/null
  perl -e 'truncate STDIN, tell STDIN'
} <> file

head여기서는 표준 입력에서 커서 위치를 이동한다는 사실을 사용합니다. 일반적 으로 head입력을 청크로 읽으면 성능이 향상되지만 POSIX에서는 가능하면 seek첫 번째 줄을 초과하자마자 반환해야 합니다. 그러나 모든 구현이 이 작업을 수행하는 것은 아닙니다.

read또는 이 경우 셸의 명령을 사용할 수 있습니다.

{ read -r dummy; perl -e 'truncate STDIN, tell STDIN'; } <> file

답변4

Ex 모드에서 Vim을 사용할 수 있습니다:

ex -sc '2,d|x' .hgignore
  1. 2,2행을 끝까지 선택하세요.

  2. d삭제

  3. x저장하고 닫습니다

관련 정보