파일의 전체 수정은 어떻게 이루어 집니까? 내 질문은이

파일의 “인플레 이스”수정 (예 : via sed -i또는 perl -imean)은 무엇입니까?
내 질문은이 내부 수정이 어떻게 수행되는지에 관한 것입니다. 복사 된 파일이 수정 작업을 수행 한 후 원본을 교체합니까? 아니면 원본 파일이 어떻게 든 수정됩니까?



답변

sed 임시 파일을 만들고 출력을 해당 파일에 쓴 다음 임시 파일 이름을 원본의 맨 위로 바꿉니다.

다음을 사용하여 어떤 일이 발생하는지 볼 수 있습니다 strace.

$ strace -e trace=file sed -i -e '' a
execve("/usr/bin/sed", ["sed", "-i", "-e", "", "a"], [/* 34 vars */]) = 0
<...trimmed...>
open("a", O_RDONLY)                     = 3
open("./sedxvhRY8", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
rename("./sedxvhRY8", "a")              = 0
+++ exited with 0 +++

이렇게 sed하면 모든 파일 작업이 기록됩니다. 새 파일을 (안전하게 O_CREAT|O_EXCL) 작성하고 데이터를 쓴 다음 원래 파일의 맨 위로 다시 이동합니다 a.

sed -i백업에 사용할 접미사를 수락하고이 경우 원본의 이름을 바꾸지 않고 원본을 먼저 이동시킵니다. 이 주장은 대부분의 BSD에서 필수적입니다 sed. 이 경우 디렉토리에 올바른 이름의 파일이 전혀없는 짧은 시간이 있습니다.

perl 최신 버전에서는 입력 파일을 연 다음 삭제하고 동일한 이름의 새 파일을 만듭니다.

open("a", O_RDONLY)               = 3
unlink("a")                       = 0
open("a", O_WRONLY|O_CREAT|O_EXCL, 0600) = 4

unlink이미 열려있는 파일 을 삭제 ( )하면 핸들을 유지하는 한 파일에 대한 액세스 권한이 유지되므로 삭제 된 파일에서 데이터를 계속 읽을 수 있습니다. 이런 식 perl으로 임시 파일이 아닌 출력 파일에 직접 씁니다. 추가 파일이 생성되지 않지만 프로세스 중에 파일을 읽으면 sed의 접근 방식 과 달리 부분 내용 이 표시됩니다. 올바른 이름을 가진 파일이없는 짧은 시간도 있습니다.이 파일은 끝이 아닌 프로세스의 시작 부분에 있습니다 (와 같이 sed -i .bak).


모두 sedperl것입니다 :

  • 기호 링크를 일반 파일로 바꾸십시오.
  • 하드 링크를 끊습니다.
  • 가능하면 그룹 소유권을 유지하십시오.
  • 기본 그룹 setgid이 아니거나 루트가 아닌 그룹이 소유 한 경우 기본 그룹 (또는 해당 디렉토리에 비트 가있는 경우 상위 디렉토리 그룹)으로 파일을 작성하십시오 .
  • 루트 인 경우 파일 소유권을 유지하십시오.
  • 기본 권한을 유지하십시오.
  • 결과 그룹이 시작한 그룹과 동일한 경우 보존 setuidsetgrp비트
  • 끈적 끈적한 비트를 유지하십시오.
  • xattrs를 보존 하지 마십시오.

sed 의지:

  • ACL 유지 (Linux의 경우 다른 사람에 대해서는 모른다) .

perl 의지:

  • ACL을 보존 하지 마십시오 .

위의 내용은 GNU 기반 Linux sed및 Mac OS X (FreeBSD 파생)에서 적용 sed됩니다.


답변

@Homer의 답변 외에도 perldoc perlrun다음에서

“<>”구문으로 처리 된 파일을 내부 편집하도록 지정합니다. 입력 파일 이름을 바꾸고 원래 이름으로 출력 파일을 연 다음 해당 출력 파일을 print () 문의 기본값으로 선택합니다. 확장명 (제공된 경우)은 다음 규칙에 따라 백업 사본을 작성하기 위해 이전 파일의 이름을 수정하는 데 사용됩니다.

확장명이 제공되지 않으면 백업이 작성되지 않고 현재 파일을 덮어 씁니다.

확장자에 *가 포함되어 있지 않으면 현재 파일 이름 끝에 접미사로 추가됩니다. 확장자에 하나 이상의 * 문자가 포함되어 있으면 각 *가 현재 파일 이름으로 바뀝니다.

그리고 소프트 링크 나 하드 링크는 유지되지 않습니다.

-i는 동일한 이름의 새 파일을 작성하기 전에 원래 파일의 이름을 바꾸거나 삭제하므로 UNIX 스타일의 소프트 및 하드 링크는 유지되지 않습니다.

마지막으로, -i 스위치는 명령 행에 파일이 제공되지 않은 경우 실행을 방해하지 않습니다. 이 경우 백업이 작성되지 않고 (원래 파일을 결정할 수 없음) 예상대로 STDIN에서 STDOUT으로 처리가 진행됩니다.

당신이 사용해야하는 이유도 설명 -i-p옵션, 또는 명시 적으로 사용 print당신이 편집 올바른 위치에 원하는 경우 문을 perl:

# Opps, file will be truncated, becomes empty
$ perl -i.bak -ne 's/123/qwe/' file

# Right way
$ perl -i.bak -ne 's/123/qwe/;print' file

# Or
$ perl -i.bak -pe 's/123/qwe/' file