mv에는 rsync 기능이 있습니다

mv에는 rsync 기능이 있습니다

공통 요소가 많은 두 디렉터리 트리를 병합하려고 하는데 각 디렉터리 트리에 두 트리 중 하나에만 존재하는 요소가 있습니다. 내가 겪고 있는 주요 문제는 mv동일한 상대 경로를 가진 두 개의 하위 디렉터리를 만날 때 소스(with -f) 또는 대상(with -n)을 유지하지만 두 하위 디렉터리 세트의 결합을 가져올 수 없다는 것입니다. . 물론 rsyncwith 를 사용할 수도 있지만 --remove-source-files그렇게 하면 실제 이동이 아닌 실제로 데이터를 복사한 다음 이전 파일을 삭제하게 됩니다. 두 디렉터리 트리 모두 수백 기가바이트의 데이터를 포함하고 있으며 둘 다 동일한 파티션에 있으므로 시간을 절약하기 위해 가능하다면 실제 이동을 수행하고 싶습니다.

이제 가지고 있지만 find * -type file -exec mv -n {} /destination/{}대상 디렉터리가 이미 존재하는 경우에만 원본에서 대상으로 파일을 이동합니다. 명령 앞에 이와 같은 접두어를 붙일 수 있지만 mv -n * /destination/그렇게 하면 최상위 디렉터리만 표시됩니다. 한 줄로 할 수 있는 방법이 있나요? 파일을 복사하기 전에 디렉터리가 존재하는지 확인하는 스크립트를 언제든지 작성할 수 있지만 이는 기본적인 작업처럼 보이고 더 쉬운 방법이 있어야 할 것 같습니다.

답변1

경고: 이 답변은 하드 링크(예: FAT)를 지원하지 않는 파일 시스템에는 적용되지 않습니다.

또 다른 옵션(휴대성이 더 높음)은 다음과 같습니다.

CD소스 디렉토리
찾다. -type f -print0 | cpio --pass-through --null --link --make-directories대상 디렉토리

cpio(복사 인&아웃)은 초기 공룡입니다 tar. 와 마찬가지로 tar아카이브를 생성하거나 아카이브에서 추출할 수 있습니다. (내가 틀렸다면 수정해주세요)와는 달리, tar단일 명령을 사용하여 디렉토리 트리를 복사할 수 있습니다. (내 생각에는 당신이 이것을 할 수 있을 것 같습니다.) 이것이 바로 그 의미입니다. "파일 이름이 null로 구분될 것으로 예상됩니다"를 의미합니다. 즉, 출력을 읽습니다. 이는 "가능한 경우 소스 디렉터리의 파일을 대상 디렉터리에 연결합니다"를 의미합니다. 설명이 필요하지 않습니다.tar -cf - source option(s) and arguments(s) | tar -xf - destination option(s) and arguments(s)--pass-through--nullfind … -print0--link--make-directories

이는 축약될 수 있습니다. 필요한 경우 또는를 추가하세요.cpio –p0ld dest_dir--verbose-v

자, 이 모든 일이 끝난 후,

  • 충돌을 확인하고 적절하게 처리하십시오.
  • 대상 디렉토리가 하드 링크로 채워져 있는지 확인하십시오.
  • 소스 디렉터리를 삭제합니다.

답변2

prename당신은 당신이 원하는 것을 얻기 위해 그것을 사용할 수 있습니다 . 일부 배포판(예: Debian/Ubuntu)에서는 기본적으로 설치되고 별칭이 지정되어야 합니다 rename. 다른 배포판에서는 다른 배포판을 사용할 수 있습니다 rename. 소스 디렉터리 위의 디렉터리로 변경하여 다음을 수행할 수 있습니다.

find source -exec prename 's:^source:/path/to/dest:' {} +

이렇게 하면 대상 트리에 이미 존재하는 파일 이동을 거부하고 디렉터리 이름이 겹치는 경우 나중에 삭제할 수 있도록 빈 디렉터리를 남겨둡니다. 기존 파일을 덮어쓰도록 -f옵션을 추가할 수 있습니다 .prename

예:

$ mkdir -p dir1/{common,sub1} dir2/{common,sub2}

$ touch dir1/sub1/file dir2/sub2/file dir1/common/common dir2/common/common dir1/common/diff1 dir2/common/diff2

$ tree dir*
dir1
├── common
│   ├── common
│   └── diff1
└── sub1
    └── file
dir2
├── common
│   ├── common
│   └── diff2
└── sub2
    └── file

4 directories, 6 files

$ find dir2 -depth -exec rename 's/^dir2/dir1/' {} +
Can't rename dir2/sub2/file dir1/sub2/file: No such file or directory
dir2/common/common not renamed: dir1/common/common already exists
dir2/common not renamed: dir1/common already exists
dir2 not renamed: dir1 already exists

$ tree dir*
dir1
├── common
│   ├── common
│   ├── diff1
│   └── diff2
├── sub1
│   └── file
└── sub2
    └── file
dir2
└── common
    └── common

4 directories, 6 files

고쳐 쓰다:

주어진 소스에는 일반적으로 prename(따라서 "p")와 함께 번들로 제공됩니다. perlDebian/Ubuntu에서는 package 의 일부입니다 perl. 혼자서 해결하고 싶다면 이 질문에 대한 답변자 중 한 명이 -내장된 이름 바꾸기 대신 Perl 이름 바꾸기 유틸리티 받기별도의 저장소를 만들었습니다.https://github.com/subogero/rename

답변3

rsync다음을 사용하여 파일을 복사하는 대신 실제로 파일을 이동할 수 있습니다 .

rsync -av --link-dest "$PWD"/src/ --remove-source-files src/ dst

일반적인 방법으로는 rsync -av --remove-source-files src/ dst파일이 에서 으로 복사된 src/다음 dst소스가 삭제됩니다. 이 옵션을 추가 --link-dest하고 디렉터리를 가리키면 src/대상 파일이 복사되지 않고 연결됩니다.

내가 볼 수 있는 유일한 경고는 다음과 같습니다.

  • --link-dest대상 디렉터리에 상대적이므로 전체 경로를 지정해야 합니다.src/
  • rsync파일이 링크되면 파일이 복사되었다고 보고되지 않으므로 출력에서는 rsync -av --progress파일이 복사되지 않았다고 보고합니다.

알아채다. 사용 가능한 디스크 공간의 90%를 소비한 파일로 테스트되었습니다. 복사는 실패하지만(90% + 90% >> 100%) 연결/이동은 제대로 작동합니다.

관련 정보