각 파일에 대해 하드 링크를 사용하여 디렉토리를 재귀 적으로 복사하는 방법


52

각 파일이 원본 파일에 대한 하드 링크 인 디렉토리 트리의 "복사본"을 만들고 싶습니다.

예 : 디렉토리 구조가 있습니다.

dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3

각 파일이 원본 파일에 대한 하드 링크 인 디렉토리 트리의 "복사본"인 예상 결과는 다음과 같습니다.

dirB/            #  normal directory
dirB/file1       #  hardlink to dirA/file1
dirB/x/          #  normal directory
dirB/x/file2     #  hardlink to dirA/x/file2
dirB/y/          #  normal directory
dirB/y/file3     #  hardlink to dirA/y/file3

답변:


50

Linux (보다 정확하게 GNU와 Linux를 커널로 사용하는 시스템에서 일반적으로 busybox구현 된 구현 cp) 및 최근 FreeBSD에서 다음과 같은 방법을 사용합니다.

cp -al dirA dirB

보다 편리한 솔루션은 Stéphane Chazelas의 pax 및 cpio를 사용한 답변을 참조하십시오.


paxFreeBSD에서 와 같이 cp -a심볼릭 링크를 하드 링크하지는 않습니다.
Stéphane Chazelas

하드 링크는 별도의 파일 시스템 마운트에서 작동하지 않습니다.
Dave

24

POSIX pax는 다음 -l옵션을 사용 하여 읽기 + 쓰기 모드에서 사용합니다 .

pax -rwlpe -s /A/B/ dirA .

( -peGNU처럼, 복사됩니다이 경우 파일의 모든 가능한 특성 (전용 디렉토리) 보존 cp의는 -a않습니다).

이제는 표준 이지만 그 명령이 반드시 이식성 이 좋은 것은 아닙니다 .

첫째, 많은 GNU / Linux 기반 시스템은 pax기본적으로 포함 되어 있지 않습니다 (비 선택적 POSIX 유틸리티 임에도 불구하고).

그런 다음 몇 가지 구현으로 여러 버그와 부적합으로 인해 해당 코드에 많은 문제가 발생합니다.

  • 버그로 인해 Solaris 10 pax(최소한) -rwl은와 함께 사용할 때 작동하지 않습니다 -s. 어떤 이유로 든 원래 경로와 복사 된 경로 모두에 대체를 적용하는 것 같습니다. 따라서 위의 link("dirB/file", "dirB/file")대신에 일부 를 시도합니다 link("dirA/file", "dirB/file").
  • FreeBSD에서는 symlinkpax 형식의 파일에 대한 하드 링크를 만들지 않습니다 (POSIX에서 허용되는 동작). 뿐만 아니라 심볼릭 링크의 대상 ( POSIX 에서는 허용 되지 않는 동작)에 대체를 적용합니다 . 예를 들어에 심볼릭 링크가 있으면에 링크 가 됩니다 .foo -> AAdirAfoo -> BAdirB

또한 내용이 $srcand에 저장된 임의의 파일 경로를 사용하여 동일하게 수행하려는 경우 내부 의 전체 디렉토리 구조 (존재하고 디렉토리 여야 함) $dstpax -rwl -- "$src" "$dst"작성하는 것이 중요합니다 . 예를 들어, 만약 이며 , 다음, 생성됩니다.$src$dst$srcfoo/bar$dst/foo/bar

대신 $dst의 사본이 $src되고 싶다면 가장 쉬운 방법은 다음과 같습니다.

absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && pax -rwlpe . "$absolute_dst")

(위에서 언급 한 대부분의 문제를 해결할 수도 있지만 $dst줄 바꿈 문자 로 끝나는 절대 경로이면 실패합니다 ).

이제는 GNU / Linux 시스템에서 도움이되지 않습니다 pax.

paxPOSIX가 tarand cpio명령 의 기능을 병합하기 위해 만든 것을 주목하는 것이 흥미 롭습니다 .

cpioA는 과거 POSIX의 발명에 반대 (1977) 유닉스 명령 및 아니라 GNU 구현 (하지가 pax하나). 따라서 더 이상 표준 명령이 아니더라도 (SUSv2에 있음) 여전히 일반적이며 일반적으로 사용할 수있는 핵심 기능이 있습니다.

에 해당 pax -rwl합니다 cpio -pl. 하나:

  1. cpio 인수와 달리 stdin에서 입력 파일 목록을 가져옵니다 (줄 바꿈으로 구분됨). 줄 바꿈 문자가있는 파일 이름은 지원되지 않습니다.
  2. 모든 파일 (일반적으로 당신은 그것을의 출력을 공급 지정할 수 있습니다 find( findcpio) 같은 사람들에 의해 공동으로 개발되었다).
  3. 메타 데이터는 유지되지 않습니다 (일부 cpio구현에는 일부를 유지하는 옵션이 있지만 이식성이없는 것은 없습니다).

그래서 cpio:

absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && find . | cpio -pl "$absolute_dst")

-s / A / B /는 내 예제에만 해당되는 것 같습니다. 소스 디렉토리 이름과 대상 디렉토리 이름이 변수 $ sourcedir 및 $ targetdir 인 경우 어떻게해야합니까?
Gudmundur Orn

@GudmundurOrn, 편집 참조.
Stéphane Chazelas

OS X에서이 명령을 실행하고 "pax : ./a.txt 파일을 자체에 연결할 수 없습니다"라는 오류 메시지가 나타납니다. 소스 디렉토리를 실제 이름으로 바꾸고 / A / B와 마지막 점을 그대로두고 명령을 그대로 사용했습니다. 내가 뭔가를 오해하고 있습니까?
db

@db -s /A/BA로 바뀌 B므로로 변경 dirA됩니다 dirB. 소스 디렉토리 이름에 no가 없으면 해당 디렉토리 A를 복사 (링크)합니다. 더 나은 접근 방법은 나머지 답변을 참조하십시오.
Stéphane Chazelas


2

하드 링크로 복사 (Copy-with-Hardlinks) 기능을 찾고 있다면 파일의 전체 또는 일부에 대한 스냅 샷 또는 백업을 살펴보십시오 rsnapshot.


1
그 흥미 롭군요. 그러나 파일이 수정되지 않으면 하드 링크는 좋은 스냅 샷 메커니즘 일뿐입니다. 권리?
Gudmundur Orn

@Gudmundur Orn; 맞습니다. 내 대답에 언급 된 도구는 파일이 고유 한 방식으로 새 스냅 샷을 만듭니다. 즉, 기존 (수정되지 않은) 파일은 하드 링크로 작성되고 새 파일 (또는 기존 파일의 수정 된 버전)은 새 파일로 작성됩니다. 따라서 중복성이 가장 적습니다.
Janis

0

@ gudmundur-orn의 대답은 정확하지만 Linux에서 BtrFS를 사용 cp a --reflink=auto dirA dirB하는 경우 트릭을 수행해야합니다. 차이로 인해 파일이 실제로 다르고 하나를 변경해도 다른 것이 변경되지 않습니다. cp -cAPFS를 사용하는 Mac에서 거의 동일하게 달성 할 수 있습니다 ( auto가능한 경우 전체 사본 -c을 작성하고 실패 함).

모든 COW 파일 시스템이이를 수행 할 수 있어야하지만 공급 업체는 표준 명령 줄 옵션에 동의하지 않았습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.