제자리에서 하드 링크를 끊으시겠습니까?


13

내 도트 파일을 버전 제어 상태로 유지하고 있으며이를 배포하는 스크립트는 하드 링크를 만듭니다. 또한 버전 관리하에 사용 etckeeper합니다 /etc. 최근에 나는 다음과 같은 경고를 받았습니다.

warning: hard-linked files could cause problems with bzr

간단한 사본 ( cp filename.ext filename.ext)은 작동하지 않습니다.

cp: `filename.ext' and `filename.ext' are the same file

여러 볼륨을 제외하고 파일 이름을 바꾸거나 파일을 이동해도 하드 링크가 끊어지지 않습니다.

그래서 내 질문은 : 실제로 해당 파일에 대한 다른 하드 링크가 어디에 있는지 알 필요없이 파일에 대한 하드 링크를 끊는 방법이 있습니까?


2
"rm"명령은 하드 링크를 끊습니다.
Johan

답변:


14
cp -p filename filename.tmp
mv -f filename.tmp filename

스크립트 작성 가능 :

dir=$(dirname -- "$filename")
tmp=$(TMPDIR=$dir mktemp)
cp -p -- "$filename" "$tmp"
mv -f -- "$tmp" "$filename"

복사본을 먼저 수행 한 다음 제자리로 옮기면 파일이 하드 링크에서 별도의 복사본으로 원자 적으로 변경된다는 이점 filename이 있습니다 (일부 또는 누락 된 시점이 없음 ).


7

아마도 하드 링크를 별도의 독립적 인 파일로 분리하고 싶을 수도 있습니다.

mv hardlink tempname && cp tempname hardlink && rm tempname

하드 링크는 디렉토리의 항목과 디스크의 inode 블록 간의 연결입니다.

inode는 파일 메타 데이터를 저장하고, 작은 파일의 경우, 일부 파일 시스템은 inode에 데이터를 저장하고, 그렇지 않으면 데이터 블록에 대한 포인터를, 매우 큰 파일의 경우 디스크 할당 단위에 대한 간접 및 이중 간접 포인터 목록을 저장합니다.

그럼에도 불구하고 파일 이름 (ls 명령이 생성하는 것)과이 메타 데이터를 저장하는 inode 블록 간의 연결을 하드 링크라고합니다.

단일 파일에 대한 여러 개의 하드 링크가 있다는 것은 하나 이상의 파일 항목에서 다른 디렉토리에있는 하나 이상의 디렉토리 항목이 참조하는 동일한 inode를 의미합니다.

rm은 디렉토리에서 파일 이름 항목을 삭제합니다. 파일에서 더 이상 inode를 참조하지 않으면 다른 파일에서 사용할 수 있도록 공간이 확보됩니다.


과연. 이것이 cpmv예가 암시 한 것입니다. 따라서 임시 파일을 사용하는 방법은 없습니다.
0xC0000022L

@ 0xC0000022L, 아니요, inode에는 다른 inode에 대한 포인터가 없습니다. 데이터 블록에 불과합니다 (또는 객체가 작 으면 데이터 공간으로 두 배가 될 수 있습니다).
vonbrand

4
복사 할 때 권한 및 기타 데이터가 보존되어 있는지 확인하십시오. 사용하십시오 cp -a(적어도 GNU coreutils).
vonbrand

@ 0xC0000022L,주의 깊게 살펴보면 원래 파일의 임시 이름 만 있으면 마지막 단계에서만 새 파일이 작성됩니다.
vonbrand

@vonbrand 사용중인 파일 시스템에 따라 실제로 사용할 수 있습니다.
Johan

4

~ / .bashrc 파일의 끝에 이것을 넣으십시오.

delink () { tmpfile="$1$(date)"; cp -a "$1" "$tmpfile"; mv "$tmpfile" "$1"; }

이렇게 실행

delink filename

3

bash 스크립트로 가장 좋은 방법은 다음과 같습니다.

if [ -f "$1" ] ; then
dir="$(dirname -- "$1")"
tmpfile="$(mktemp --tmpdir="$dir")"
cp --preserve=all -f -- "$1" "$tmpfile"
mv -f -- "$tmpfile" "$1"
fi

참고 사항 :

  • 파일을 복사하기 전에 파일이 일반 파일인지 확인하십시오
  • 사본이 준비 될 때까지 이전 파일을 제자리에 유지하십시오
  • mktemp존재하지 않는 파일을 생성하는 데 사용
  • -f덮어 쓰기 및 --preserve=all메타 데이터를 가능한 원본 파일과 유사하게 유지 하는 데 사용
  • 사용 --"경로에 공백이 포함 및 / 또는로 시작 인용-

현재 (3.16) Linux 시스템 호출에서는 임시 파일을 만들지 않고 교체를 수행 할 수 없습니다. 파일을 원자 적으로 덮어 쓸 수는 있지만 (예 : 이전 파일을 제거하고 단일 작업으로 새 파일로 교체 할 수 있음) 파일 시스템에 이름이없는 파일 (즉, 함수 O_TMPFILE플래그를 사용하여 생성 된 임시 파일 open) rename에서는 파일 이름을 입력으로 요구 하기 때문에 ( rename파일 설명자를 입력으로 사용하는 버전은 없습니다) - 자세한 내용은 여기 를 참조하십시오)


1
dirnamemktemp통화 에서 이름을 인용하지 못했습니다 . 당신을 위해
그것을 고쳤다

@derobert oh 감사합니다. 중첩 된 큰 따옴표가 있기 때문에 작동하지 않습니다 ... 다른 수정이 필요합니다! Kinda 증오 bash
pqnet

3
$( ... )-style 명령 대체로 인해 작동 합니다. ` ... `스타일 보다 좋은 이유 중 하나 입니다.
derobert

@derobert nice, 몰랐습니다. 또한 인라인 코드 태그 안에`를 어떻게 사용할 수 있습니까?
pqnet

백 슬래시로 이스케이프 할 수 있습니다. 그래서 `당신이 넣을 수 있도록 : `\``(물론, 당신이 입력 한 것을 보여주기 위해 두 번 탈출했습니다).
derobert

-1

당신이 찾고있는 명령은 unlink


아마도 내 질문이 명확하지,하지만하여 "제자리"와 함께 예 cpmv내가 이후에 존재하는 파일을 원하는 것이 분명하게 의미했다.
0xC0000022L

아, 나는 그것을 명확하게 찾지 못했습니다. 그렇다면 요한의 대답을 따라야합니다.
Jenny D

1
"unlink"명령은 단순히 파일을 제거합니다 (unlink () 시스템 호출의 기능).
Raúl Salinas-Monteagudo

-1

이 파일에 하드 링크 된 모든 파일 이름을 찾고 있다면 다음을 사용할 수 있습니다.

find -samefile myknowhardlinkfile

또한 ls -il myknowhardlinkfile동일한 inode (세번째 필드)에 하드 링크 된 파일 이름의 수를 보여줍니다.

101612442 -rw-rw-r--. 2 me me 0 Aug  5 07:07 myknowhardlinkfile

유용 할 수는 있지만 실제로 질문에 대답하지는 않습니다.
Flimm
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.