특정 패턴과 일치하는 여러 파일에 일부 텍스트를 추가하는 명령을 작성 중입니다.
for file in $(find . -name "*.txt"); do sed "1s/^/hello/" $file; done
stdout
다른 파일(예 : ) 에 쓰면 "$file.bak"
모든 것이 계획대로 진행되지만 명령을 사용하여 동일한 파일에 다시 쓰려고 하면 파일 내용이 지워집니다.
for file in $(find . -name "*.txt");do sed "1s/^/hello/" $file > $file; done
나는 이 동작이 놀랍다고 생각합니다. 왜 이런 일이 발생하는지 개념적으로 설명할 수 있는 사람이 있습니까? 나는 동일한 효과 bash
로 macOS에서 이것을 시도했습니다 .zsh
(나는 sed -i ""
제자리에 쓰는 것에 대해 알고 있지만, 제자리에 쓰기 전에 결과를 다른 명령으로 파이프하고 싶습니다.)
답변1
개념적 놀라움은 이 진술에 있을 수 있습니다.
하지만 동일한 파일에 명령을 다시 쓰려고 하면
사용하면 다시 쓰기 위해 파일을 여는 cmd file > file
대신 cmd
셸 자체를 엽니다. 이를 발견했을 때 쉘이 가장 먼저 하는 일은 > file
쓰기 모드로 위치 0에서 파일을 열고(따라서 파일이 잘림) stdout을 파일로 리디렉션하는 것입니다. 따라서 cmd
읽기 시작하는 순간 file
이미 비어 있습니다.
또는 더 공식적으로는 다음과 같습니다.
cmd
Shell은 실행할 새 프로세스를 분기합니다.- 새 프로세스(여전히 실행 중인 쉘 코드)가
file
위치 0에 쓰기 위해 열립니다(따라서 잘림). - 새로운 프로세스 실행은
cmd
실제로 현재 프로세스 내에서 새로운 바이너리를 시작합니다. cmd
런타임 표준 출력은 다음을 가리킵니다.file
cmd
읽기 위해 열었file
지만 지금은 비어 있습니다.
반면, sed -i '1s/^/hello/' file
별도로 관리되는 파일을 사용하는 경우 sed
(기술적으로는 백그라운드에 임시 파일을 생성합니다.)