Program Club

Bash를 사용하여 한 디렉토리를 다른 디렉토리로 어떻게 병합합니까?

proclub 2020. 11. 6. 20:56
반응형

Bash를 사용하여 한 디렉토리를 다른 디렉토리로 어떻게 병합합니까?


한 디렉토리에서 다른 디렉토리로 파일을 병합하는 쉘 스크립트를 찾고 있습니다.

견본:

html/
  a/
    b.html
  index.html

html_new/
  a/
    b2.html
    b.html

용법:

./mergedirs.sh html html_new

결과:

html/
  a/
    b.html
    b2.html
  index.html

html/a/b.html에 의해 교체 html_new/a/b.html
html/a/b2.html되었습니다 복사 html_new/a/b2.html
html/index.html되었습니다 그대로 유지되었습니다


당신은 아마 원할 것입니다 cp -R $1/* $2/-그것은 재귀 적 사본입니다.

(숨겨진 파일 (이름이 점으로 시작하는 파일)이있는 경우 해당 명령에 접두사를 붙여 shopt -s dotglob;일치하는지 확인해야합니다.)


cp -RT source/ destination/

의 모든 파일과 디렉토리 sourcedestination. 예를 source/file1들어은 destination/file1.

-T플래그는 정지 source/file1에 복사되는 destination/source/file1대신. (안타깝게도 cpmacOS에서는 -T플래그를 지원하지 않습니다 .)


rsync 살펴보기

rsync --recursive html/ html_new/

Rsync는 많은 플래그를 설정 했으므로 자세한 내용은 rsync 맨 페이지를 참조하십시오.


rsync를 사용하십시오. 원격 복사 외에도 로컬 파일 복사 및 병합을위한 훌륭한 도구입니다.

rsync -av /path/to/source_folder/ /path/to/destination_folder/

source_folder의 내용 만 대상에 복사하려면 소스 폴더의 후행 슬래시가 필요합니다. 해제하면 source_folder 그 내용 이 복사됩니다 . 폴더를 병합하려고하므로 찾고있는 내용이 아닐 수 있습니다.


cd html
cp -r . /path/to/html_new

cp -r작동 하지 않습니까?

cp -r html_new/* html

또는 (첫 번째 버전은 ".something"파일을 복사하지 않기 때문에)

cd html_new; cp -r . ../html

주의하시기 바랍니다 -r 파이프에서 읽고 복사 된 디렉토리에있는 파일의 파이프가있는 경우. 이를 방지하려면 -R대신 사용하십시오.


이 질문과 그에 대한 대답은 오래되었지만 현재 사용하는 기존 질문은 cp일부 가장자리 사례를 처리하지 않거나 대화식 작업이 필요 하기 때문에 내 대답을 추가하고 있습니다 . 종종 가장자리 케이스 / 스크립팅 / 휴대 / 다중 소스하지 문제가 있지만, 그 경우 단순 승리, 그리고 그것을 사용하는 것이 좋습니다 cp인지 부하를 줄이기 위해 (다른 답변에서와 같이) 덜 플래그와 함께 직접 -하지만 사람들을 위해 다른 배 (또는 강력하게 재사용 가능한 함수의 경우)이 호출 / 함수는 유용하며 우연히 bash에 한정되지 않습니다 (이 질문은 bash에 관한 것이기 때문에이 경우 보너스 일뿐입니다). 일부 플래그는 축약 될 수 있지만 (예 :로 -a), 모든 플래그 를 긴 형식으로 명시 적으로 포함했습니다 (예외 :-R, 아래 참조). 특별히 원하지 않는 기능이 있으면 플래그를 제거하십시오 (또는 POS가 아닌 OS에 있거나 버전이 cp해당 플래그를 처리하지 않는 경우-GNU coreutils 8.25에서 테스트했습니다 cp).

mergedirs() {
    _retval=0
    _dest="$1"
    shift
    yes | \
        for _src do
            cp -R --no-dereference --preserve=all --force --one-file-system \
                  --no-target-directory "${_src}/" "$_dest" || { _retval=1; break; }
        done 2>/dev/null
    return $_retval
}

mergedirs destination source-1 [source-2 source-3 ...]

설명:

  • -R:에서 미묘하게 다른 의미가 -r/ --recursive에 설명 된대로 (특히 소스 DIRS의 특수 파일에 대한) 일부 시스템을 이 답변
  • --no-dereference: SOURCE의 심볼릭 링크를 따르지 마십시오.
  • --preserve=all: 지정된 속성 (기본값 : mode, ownership, timestamps)을 보존합니다. 가능한 경우 추가 속성 : context, links, xattr, all
  • --force: 기존 대상 파일을 열 수없는 경우 제거하고 다시 시도하십시오.
  • --one-file-system:이 파일 시스템에 유지
  • --no-target-directory: treat DEST as a normal file (explained in in this answer, namely: If you do a recursive copy and the source is a directory, then cp -T copies the content of the source into the destination, rather than copying the source itself.)
  • [piped input from yes]: even with --force, in this particular recursive mode cp still asks before clobbering each file, so we achieve non-interactiveness by piping output from yes to it
  • [piped output to /dev/null]: this is to silence the messy string of questions along the lines of cp: overwrite 'xx'?
  • [return-val & early exit]: this ensures the loop exits as soon as there is a failed copy, and returns 1 if there was an error

BTW:

  • A funky new flag which I also use with this on my system is --reflink=auto for doing so-called "light copies" (copy-on-write, with the same speed benefits as hard-linking, and the same size benefits until and in inverse proportion to how much the files diverge in the future). This flag is accepted in recent GNU cp, and does more than a no-op with compatible filesystems on recent Linux kernels. YMWV-a-lot on other systems.

참고URL : https://stackoverflow.com/questions/4572225/how-do-i-merge-one-directory-into-another-using-bash

반응형