이것:
echo 'some text' > file.txt
cat file.txt > file.txt
분명히 나에게 빈 파일을주는 것 같습니다.
그러나 또한 나를 놀라게 한 것은 다음과 같습니다.
cat2 () {
cat "$@" > tmp.txt
cat tmp.txt
return $?
}
echo 'some text' > file.txt
cat2 file.txt > file.txt
.tmp.txt
file.txt
이 방법도 통하지 않아요! :
echo 'some text' > file.txt
cat file.txt | cat2 > file.txt
파일이 계속 지워지는 이유는 무엇입니까?
답변1
주문
cat2 file.txt > file.txt
새로운 빈 공간을 만들 것입니다file.txt
앞으로함수 를 호출합니다 cat2
.
따라서 런타임 시 cat2
파일은 비어 있으므로 cat
빈 출력이 발생합니다.
작업 순서를 깨는 데 도움이 된다면, 당신이 한 일은 다음과 같습니다.
- 콘텐츠가 포함된 file.txt 파일을 만듭니다.
- 새 빈 파일 file.txt를 만듭니다.
- cat2를 실행하고 file.txt로 출력합니다.
이는 리디렉션 연산자가 cat2
실행 전에 발생하기 때문입니다.
답변2
tr
다음 구성은 작동합니다( 예제 작업 으로 사용됨 ).
{ 'rm' -f File.txt && tr '[:lower:]' '[:upper:]' > File.txt; } < File.txt
입력 리디렉션은 < File.txt
블록의 항목을 실행하기 전에 먼저 파일을 중괄호 안의 명령문에 표준 입력으로 할당합니다.
파일에 열린 파일 설명자가 있으므로 블록 내에서 파일을 삭제해도 내용은 삭제되지 않습니다. 옵션 rm
사용과 같은 가능한 앨리어싱 상황을 피하기 위해 따옴표를 붙였습니다 -i
.
출력 리디렉션은 원본 파일과 동일한 이름을 가진 새 출력 파일(inode)을 생성합니다. 종료 되면 tr
새 파일이 닫힙니다.
마지막으로 입력 리디렉션이 완료되고 이제 디렉터리나 파일 설명자를 통한 연결이 없으며 해당 리소스가 해제됩니다.
Stéphane Chazelas의 뛰어난 의견을 바탕으로 편집되었습니다.
(a) 모든 프롬프트와 오류를 방지할 수 있는 옵션이 있어야 rm
합니다 .-f
(b) tr
로케일 독립적인 문자 클래스를 사용해야 합니다.
(c) 새 File.txt는 다른 inode 번호, 생성 시간 및 가능한 경우 소유권, 권한, acl 또는 기타 확장 속성을 포함하여 이전 File.txt와 독립적입니다. 또한 심볼릭 링크를 일반 파일로 대체하고 하드 링크를 분리하여 원본 데이터를 다른 경로 이름으로 유지합니다.