폴더 내의 모든 하드 링크 끊기


10

하드 링크가있는 특정 파일 수를 포함하는 폴더가 있습니다 (동일한 폴더 또는 다른 곳에 있음).이 파일을 하드 링크 해제하여 독립적으로 만들고 내용을 변경해도 아무런 영향을 미치지 않습니다. 다른 파일 (링크 수는 1이 됨)

아래에는 기본적으로 각 하드 링크를 다른 위치로 복사 한 다음 제자리로 옮기는 솔루션이 있습니다.

그러나이 방법은 다소 조잡하고 오류가 발생하기 쉬우므로 파일을 하드 링크 해제하는 명령이 있는지 알고 싶습니다.

조잡한 답변 :

하드 링크가있는 파일 찾기 ( 편집 : 하드 링크가 있는 소켓 등을 찾으려면 find -not -type d -links +1)을 사용 하십시오.

find      -type f -links +1 # files only
find -not -type d -links +1 # files, sockets etc.

파일의 하드 링크를 해제하는 다른 방법 (파일을 다른 위치로 복사 한 후 다시 이동) : 편집 : Celada가 말했듯이 타임 스탬프 및 권한을 잃지 않도록 아래에서 cp -p를 수행하는 것이 가장 좋습니다. 편집 : 임시 파일을 만들고 임시 파일을 덮어 쓰지 않고 파일 아래에 파일로 복사하면 mv명령이 여전히 위험 하지만 (@Tobu 덕분에) 일부 데이터를 덮어 쓸 위험이 최소화 됩니다. 편집 : 동일한 파일 시스템 (@MikkoRantalainen)에 임시 디렉토리를 작성하십시오.

# This is unhardlink.sh
set -e
for i in "$@"; do
  temp="$(mktemp -d -- "${i%/*}/hardlnk-XXXXXXXX")"
  [ -e "$temp" ] && cp -ip "$i" "$temp/tempcopy" && mv "$temp/tempcopy" "$i" && rmdir "$temp"
done

(그래서, 모든 하드 링크를 해제 하드 링크 편집 : 변경 -type f-not -type d위 참조)

find -not -type d -links +1 -print0 | xargs -0 unhardlink.sh

나는 그 '원유'를 고려하지 않을 것입니다. 더 빨리 얻는 유일한 방법은 sendfile () 시스템 호출로 약간의 트릭을 수행하고 오픈 소스 파일을 링크 해제하고 대상을 제자리에 다시 쓰는 것입니다. 솔직히 노력할만한 가치가 없습니다.
Matthew Ife

내가 사용하여이 명령을 실행했을 때 '원유', 나는 그 의미, 예를 들어, cp -i스위치, 그것은 오버라이드 (override) 할 필요가 묻는 나에게 몇 가지 메시지를 뱉었다 ./fileXXXXXX합니다 ( $temp, TMPFILE는 고유 한 파일 이름을 지정한다하더라도, 파일)이 있도록 해야 일종의 경쟁 조건 또는 그 밖의 모든 것이 될 수 있으며 일부 데이터를 잃을 위험이 있습니다.
수잔 듀 페론

1
파일이 존재하는 것은 정상이며 방금 tempfile로 파일을 만들었습니다 (nb : mktemp를 위해 더 이상 사용되지 않지만 문제의 원인은 아닙니다).
Tobu

1
귀하는 unhardlink.sh필요 unhardlinked 될 수있는 파일이 들어있는 같은 디렉터리 내부의 임시 디렉토리를 작성해야합니다. 그렇지 않으면 재귀 호출이 다른 파일 시스템 내에서 재귀하고 임시 디렉토리가 현재 작업 디렉토리에 있기 때문에 파일 시스템 경계를 넘어 물건을 이동하게 될 수 있습니다. "$(dirname "$i")/hardlink-XXXXXX"대신 mktemp에 인수로 전달할 수 있다고 생각합니다 .
Mikko Rantalainen

1
@MikkoRantalainen 감사합니다. 많이 업데이트되었습니다! 파일 시스템이 일종의 unionfs 또는 fuse파일 시스템 인 경우 실제로 는와 path/to/hardlink-XXX다른 물리적 저장 매체로 디스패치 할 path/to/original-file수 있지만 이에 대해 수행 할 수있는 것은 많지 않습니다.
수잔 Dupéron

답변:


9

스크립트에 개선의 여지가 있습니다 (예 : 명령에 -p옵션 cp추가). 그러나 솔루션의 기본 아이디어는 작동하는 유일한 아이디어입니다. 파일을 하드 링크 해제하려면 파일을 복사 한 다음 사본을 원래 이름으로 다시 이동해야합니다. "조잡한"솔루션은 없으며이 프로세스는 다른 프로세스가 파일에 동시에 액세스하는 경우 경쟁 조건을 갖습니다.


사실, 나는 물건을 복사 할 때 항상 cp -a를 사용하여 모든 것을 보존하고 심볼릭 링크를 심볼릭 링크로 재귀하고 복사합니다. 이번에 왜 잊어 버렸는지 모르지만 귀하의 답변을 본 후 모든 타임 스탬프를 망쳐 서 백업에서 (아주 고통스럽게) 복구해야한다는 것을 알았습니다.
Suzanne Dupéron

5

디스크 공간을 구우 고 비교적 최신 버전 tar(예 : Ubuntu 10.04 및 CentOS 6에있는 버전)이있는 경우이 --hard-dereference옵션 을 사용할 수 있습니다 .

다음과 같은 것 :

$ cd /path/to/directory
$ ls -l *
bar:
total 12
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 2 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 2 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

(내가 달린 곳 ln foo/[12] bar)

$ tar cvf /tmp/dereferencing.tar --hard-dereference .
$ tar xvf /tmp/dereferencing.tar
$ ls -l *
bar:
total 12
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 3

foo:
total 12
-rw-rw-r-- 1 cjc cjc 3 May  6 19:07 1
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 2
-rw-rw-r-- 1 cjc cjc 2 May  6 19:07 4

매뉴얼 페이지에서 :

   --hard-dereference
          follow hard links; archive and dump the files they refer to

나는 할 수없는 작은 타르가 있다고 생각합니다. 좋은 수정입니다.
Joseph Kern

디스크 공간이 부족하여 모든 것을 복사 할 수 없다는 것을 언급하지 않았습니다. 기본적으로 cp -a --no-preserve=links /path/to/folder /path/to/copy && rm -rf /path/to/folder && mv /path/to/copy /path/to/folder실수하지 않은 경우 와 같은 방법입니다 . tar는 디스크 탐색을 줄이고 스 래싱을 줄이기 때문에 방법이 더 효율적이라고 생각합니다. rsync를 사용하면 cp 방법보다 성능이 훨씬 낮습니다.
Suzanne Dupéron

1
여분의 디스크를 많이 사용하지 않으려면 다음과 같이 실행하는 것이 가능 tar cvf - --hard-dereference . | tar xf -하지만 경쟁 조건이 발생하여 폭발 할 수 있습니다. 나는 그것을 시도하지 않았다.
cjc
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.