나는 읽었습니다:파일을 제자리에서 수정하는 방법이 있나요?
임시 파일을 생성하지 않는 명령어를 이용해서 그 자리에서 파일을 수정하는 방법이 있는지 궁금합니다. 디렉토리를 생성
mkdir read_only
한 다음 read_only에 일부 파일을 생성한다고 가정합니다. 파일 생성이 성공적으로 완료되면 를 실행합니다 chmod 555 read_only
. 이제 임시 파일을 사용하지 않고도 파일을 수정할 수 있습니까? 특히, 저는 bash 스크립트를 통해 수행할 수 있는 솔루션을 원합니다. 이것이 가능한지 알고 싶지 않습니다. 또한 해결책을 찾고 있습니다. 지금까지 bash/unix 명령 관리를 사용하여 얻은 모든 아이디어는 임시 파일을 생성합니다.
편집: 내 질문이 중복되지 않은 것 같습니다."쓰기" 권한이 있는 파일을 편집할 수 있지만 상위 디렉터리는 편집할 수 없습니까?다음과 같은 이유로:
- 나는 단지 "예"라고 묻는 것 이상의 해결책을 찾고 있습니다. 그리고 그들이 묻는 것은 "예"뿐이었습니다.
- 어쩌면 중복 답변이 내 질문에 완전히 대답하지 못할 수도 있습니다. Bash 스크립트에 넣을 수 있는 명령을 요청합니다.
답변1
디렉터리에 있는 파일을 생성하거나 삭제하려면 디렉터리에 대한 쓰기 권한이 필요하지만, 디렉터리에 있는 파일에 쓸 수는 없습니다. 대부분의 셸 명령은 출력 파일이 제공되면 단순히 쓰기 위해 파일을 열고 파일의 이전 데이터를 바꿉니다. 리디렉션 >
연산자는 기존 파일을 자르고(즉, 기존 파일 내용을 삭제하여 파일 길이가 0이 됨) 쓰기를 시작합니다. 리디렉션 >>
연산자를 사용하면 데이터가 파일 끝에 추가됩니다.
파일 쓰기는 저수준 인터페이스에서 제공하는 가능성에 따라 제한됩니다. 파일의 바이트를 제자리에 덮어쓰고, 파일 끝에 추가하고, 파일을 선택한 길이로 자를 수 있습니다. 다음 바이트를 앞으로 이동하는 동안(예: foobar
→ fooNEWSTUFFbar
) 바이트를 삽입하거나 후속 바이트를 뒤로 이동하는 동안(예: foobar
→ for
) 바이트를 삭제할 수 없습니다. 단, 이동하려는 데이터를 읽고 새 위치에 기록하여 이러한 작업을 시뮬레이션하는 경우는 제외됩니다.
파일을 제자리에서 편집할 때 문제는 문제가 발생하는 경우(프로그램 오류, 디스크 가득 참, 정전 등) 파일 내용의 일관성을 유지하기 어렵다는 것입니다. 그렇기 때문에 강력한 파일 처리에는 새 데이터로 임시 파일을 작성한 다음 해당 임시 파일을 제자리로 이동하는 작업이 포함되는 경우가 많습니다.
파일 편집의 또 다른 제한 사항은 읽기 및 쓰기와 관련된 복잡한 작업이 원자적이지 않다는 것입니다. 이는 파일을 수정하는 동안 다른 작업에서 파일을 읽으려는 경우에만 문제가 됩니다. 예를 들어, 마지막 3바이트를 읽고( ) 새 데이터를 쓰고( → ) 마지막으로 이전 꼬리를 추가( → )하여 로 변경하면 foobar
동시 판독기는 파일 상태의 다른 부분도 볼 수 있습니다. 부분적으로 작성된 데이터만 포함합니다. . 다시 말하지만, 임시 파일을 제자리로 이동하는 것은 원자적 작업이므로 먼저 임시 파일에 쓰면 이 문제가 해결됩니다.fooNEWSTUFFbar
bar
foo
fooNEWSTUFF
fooNEWSTUFF
fooNEWSTUFFbar
fooNEWSTUFF
이러한 제한 사항에 신경 쓰지 않는다면 해당 위치에서 파일을 수정할 수 있습니다. 데이터를 추가하는 것은 쉽습니다( >>
). 대부분의 다른 변환은 더 복잡합니다. 일반적인 함정은
somefilter <somefile >somefile
파일 내용에 적용할 수 없음 somefilter
: 연산자는 >
읽기를 시작하기 전에 출력 파일을 자릅니다.somefilter
Joey Hess의 moreutils라는 파일이 포함되어 있습니다.sponge
이로써 문제가 해결되었습니다. 출력을 로 리디렉션하는 대신 somefile
에 파이프하여 sponge
모든 입력을 읽고그 다음에읽기 입력으로 기존 파일을 덮어씁니다. 필터가 실패하더라도 여전히 부분적인 데이터를 얻을 수 있습니다.
somefilter <somefile | sponge somefile
없는 경우 sponge
이 문제를 해결하는 이식 가능하고 쉬운 방법은 먼저 데이터를 메모리로 읽는 것입니다.
content=$(cat somefile; echo a)
content=${content%a}
이 echo a
비트는 파일 끝의 개행을 유지하는 데 사용됩니다. 명령 대체는 항상 후행 개행을 제거합니다. 그런 다음 콘텐츠를 명령에 전달할 수 있습니다.
printf %s "$content" | somefilter >somefile
그러면 파일 내용이 필터 출력으로 대체됩니다. 어떤 이유로든 명령이 실패하면 파일의 원래 내용은 손실되고 파일에는 실패하기 전에 명령으로 쓴 모든 데이터가 포함됩니다.
대부분의 쉘은 널 바이트를 지원하지 않기 때문에 이 방법은 바이너리 파일에서는 작동하지 않습니다.
파일을 수정하는 또 다른 방법은 다음을 사용하는 것입니다.ed
sed와 매우 유사한 편집기 sed
이지만 sed의 한 줄씩 작업하는 대신 파일을 메모리에 로드하고 해당 위치에 저장합니다.
파일을 메모리에 로드하거나 임시 파일을 생성하지 않고 표준 쉘 도구를 사용하여 파일을 조작하는 것은 더 까다롭지만 가능합니다. 쉘 리디렉션 및 대부분의 텍스트 처리 유틸리티에서는 파일에 추가하거나 처음부터 덮어쓰는 것만 허용합니다. 이를 사용하면 dd conv=notrunc seek=…
발견되지 않은 부분에 영향을 주지 않고 파일의 오프셋에 있는 데이터를 덮어쓸 수 있습니다 .파일을 제자리에서 수정하는 방법이 있나요?예를 들어.
답변2
디렉터리가 읽기 전용이지만 디렉터리의 파일이 읽기/쓰기인 경우 해당 파일을 덮어쓰는 것을 막을 수 있는 방법은 없습니다.
스크립트에서 일반적인 리디렉션을 사용하여 파일 에 쓰거나 >
.>>
cp
할 수 없는 일은 디렉터리에 새 파일을 만들고 기존 파일 위에 이름을 바꾸는 것입니다. 이름 바꾸기는 원자적으로 발생하므로 일반적으로 새 파일을 만들고 이름을 바꾸는 것이 좋습니다. 이는 데이터 손실을 방지하고 일반 이름으로 파일을 읽는 다른 프로세스가 업데이트 중에 파일의 일부만 보는 것을 방지합니다.
새 파일을 생성하고 이름을 바꾸는 기능이 없다는 것은 파일을 업데이트할 때 필요한 보장 사항에 대해 매우 신중하게 생각해야 함을 의미합니다.
답변3
진주의Tie::File
기준 치수진정한 내부 편집 기능을 제공합니다.
perl -MTie::File -e '
tie @a,"Tie::File","your_file_here";
# Do something...
'
이렇게 하면 요소가 @a
파일 줄에 들어가고, @a
파일이 읽기 전용 디렉터리에 있더라도 파일에 대한 모든 변경 사항이 파일에 반영됩니다.
답변4
캔트. sed 또는 perl -i
스위치를 사용하여 읽기 전용 디렉터리의 파일을 편집 할 수 없습니다 . 올바르게 가정한 대로 필요한 임시 파일을 생성하는 것이 허용되지 않습니다.
$ ls -ld read_only/
dr-xr-xr-x 2 terdon terdon 4096 Apr 13 02:16 read_only/
$ ls -l read_only/file
-rw-r--r-- 1 terdon terdon 3 Apr 13 02:16 read_only/file
$ sed -i 's/a/A/' read_only/file
sed: couldn't open temporary file read_only/sedOEdv8L: Permission denied
$ perl -i -pe 's/a/A/' read_only/file
Can't remove read_only/file: Permission denied, skipping file.
그러나 Joseph.R의 멋진 Perl 트릭을 사용할 수 있습니다.
$ perl -MTie::File -e 'tie @a,"Tie::File","$ARGV[0]"; $a[0]=~s/a/A/' read_only/file