파일을 교체 할 때 파일 권한 유지 (또는 복원)


11

파일을 인수로 허용하고 파일을 수정 한 다음 두 번째 인수에 지정된 파일 이름에 파일을 쓰는 명령이 있습니다. 나는 그 프로그램을 부를 것이다 modifyfile.

나는 그것이 "제자리에서"작동하기를 원했기 때문에 임시 파일로 수정 한 다음 다시 이동시키는 쉘 스크립트 (bash)를 작성했다.

TMP=`mktemp`
modifyfile "$original" "$TMP"
mv -v "$TMP" "$original"

이 파일에 대한 사용 권한을 삭제하면 불행한 부작용이 있습니다. 파일은 기본 권한으로 다시 만들어집니다.

mv권한을 변경하지 않고 대상을 덮어 쓰도록 명령에 지시 하는 방법이 있습니까? 또는 사용자, 그룹 및 권한을 원본에서 저장하고 복원하는 방법이 있습니까?

답변:


10

을 사용하는 대신 mv리디렉션하십시오 cat. 예를 들면 다음과 같습니다.

TMP=$(mktemp)
modifyfile "$original" "$TMP"
cat "$TMP" > "$original"

파일 수준에서 아무 것도 건드리지 않고 $original의 내용으로 덮어 씁니다 $TMP.


일부 프로그램에 파일에 대한 열린 파일 핸들이 있으면 문제가되지 않습니까?
Martin von Wittich

2
나는 다음에 가질 rm "$TMP"뿐만 아니라,하지만 내가 원하는 바로 할 것으로 보인다.
Stephen Ostermiller

@MartinvonWittich mv대신 에 사용한다면 문제가 될 것입니다 . 그 문제를 해결할 방법이 없습니다.
strugee

2
@MartinvonWittich 예. Create-new-then-move는 원자 적 변경을 제공하며 파일을 연 프로그램에는 영향을 미치지 않지만 새 파일을 생성하므로 파일의 소유권과 권한이 손실됩니다. Truncate-existing-then-then-write는 권한과 소유권을 유지하지만 충돌이 발생하면 데이터를 잃어 버리고 파일이 열려있는 프로그램의 발 아래에서 깔개를 슬쩍합니다. 둘 다 좋은 부분을 결합 할 수는 없습니다.
Gilles 'SO- 악한 중지'

1
@MartinvonWittich chown는 루트로만 작동합니다. chmodchgrp또는 사용자의 권한에 따라 작동하지 않을 수 있습니다. ACL 또는 파일 시스템 특정 확장 속성과 같은 다른 속성은 복사하지 않습니다.
Gilles 'SO- 악마 그만'

10

파일을 새 버전으로 바꾸는 두 가지 전략이 있습니다.

  1. 새 버전으로 임시 파일을 만든 다음 제자리로 이동하십시오.

    • 장점 : 프로그램이 해당 파일을 열면 이동 전후에 파일을 열 었는지 여부에 따라 이전 내용 또는 새 내용을 읽습니다. 믹스 업이 없습니다.
    • 장점 : 충돌이 발생하면 이전 내용이 유지됩니다.
    • 단점 : 새 파일이 만들어 지므로 파일 속성 (소유권, 권한 등)이 유지되지 않습니다.
  2. 기존 파일을 덮어 씁니다.

    • 장점 : 파일의 속성이 유지됩니다.
    • 단점 : 충돌이 발생하면 파일을 절반 만 쓸 수 있습니다.
    • 단점 : 프로그램을 업데이트 할 때 파일이 열려 있으면이 프로그램은 일치하지 않는 데이터를 읽을 수 있습니다.

가능하면 방법 1을 사용하지만 먼저 원본 파일의 속성을로 복제하십시오 cp -p --attributes-only. 여기에는 GNU coreutils (즉, 비 임베디드 Linux 또는 충분히 Linux와 유사한 환경)가 필요합니다. 당신의 경우 cp가없는 --attributes-only,이 옵션을 생략 : 그것은 작동 것이다 그러나 그것은뿐만 아니라 데이터를 복제 할 수 있습니다.

tmp=$(mktemp)
cp -p --attributes-only "$original" "$tmp"
modifyfile "$original" "$tmp"
mv -f "$tmp" "$original"

기존 파일의 속성을 복제 할 수없는 경우 (예 : 파일에 대한 쓰기 권한이 있지만 소유하지 않고 소유자를 보존하려는 경우) 방법 2 만 가능합니다. 데이터 손실 위험을 최소화하려면

  • 파일이 불완전한 창을 가능한 작게 만드십시오. 임시 파일에서 먼저 데이터를 준비한 다음 제자리에 복사하십시오.
  • 이전 파일을 먼저 백업하십시오.

tmp=$(mktemp)
backup="${original}~"
modifyfile "$original" "$tmp"
cp -p "$original" "$backup"
cp -f "$tmp" "$original"

좋은 대답입니다! 요즘에는 방법 1 에서 --attributes-only 인수 를 cp 명령 과 함께 사용하는 것이 좋습니다 . 이런 식으로 파일의 내용을 복사하는 데 리소스를 사용하지 않습니다. 이 인수가 추가 된 버전을 찾을 수 없습니다. cp -p --attributes-only "$original" "$tmp"
Marcelo Barros 12

@MarceloBarros 2010-10-15에 릴리스 된 GNU coreutils 8.6에 추가되었으므로 요즘 GNU coreutils가 있으면이를 가져야합니다. 다른 cp구현 에는 여전히 그런 것이 없습니다 .
Gilles 'SO- 악마 그만해'

5

첫 번째 답변에 대한 토론 후에 다른 답변을 제안합니다.

TMP="$(mktemp "$original".XXXXXXXXXX)"
modifyfile "$original" "$TMP"
chmod --reference="$original" "$TMP"
chown --reference="$original" "$TMP"
mv -f "$TMP" "$original"

비고 :

  • 내가 사용 $originalmktemp임시 파일에 저장되지 않도록 템플릿 /tmp하지만 같은 폴더에 $original. 나는 경우에 있다고 생각 /tmpIS가 다른 파일 시스템에 장착 된 작업이 더 이상 원자 없을 것이다.
  • mktemp공백이 포함 된 경우 결과 가 인용됩니다.
  • $()더 깨끗하다고 ​​생각하기 때문에``대신 사용 합니다.
  • ch{mod,own} --reference의 권한을 전송하는 데 사용됩니다 $original$TMP. 누군가 메타 데이터를 전송할 수 있고 전송해야 할 아이디어가 더 있다면 내 게시물을 편집하여 추가하십시오.
  • Gilles가 지적한 것처럼 루트 권한이 필요합니다. 글쎄, 나는 이것을 작성 했으므로 이것을 버리지 않을 것이다. : P
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.