유사한 디렉터리 트리의 동일한 위치 간에 자동으로 복사

유사한 디렉터리 트리의 동일한 위치 간에 자동으로 복사

저는 두 대의 컴퓨터에 큰 파일 시스템 트리를 유지 관리하고 있으며 종종 한 컴퓨터에서 다른 컴퓨터로 하나 또는 몇 개의 파일을 복사해야 합니다.

길고 동일한 경로를 입력하지 않고도 두 트리의 동일한 위치 간에 자동으로 복사할 수 있습니까?


예를 들어, 를 지정하지 않고 myroot/a/b/c파일을 복사하고 싶습니다 .remoteroot/a/b/ca/b/c

이 같은:

myroot/a/b/c$: smartcopy myfile --destination-root remoteroot

답변1

유틸리티 rsync-R옵션은 어느 정도 도움이 될 수 있지만 다음 단계를 거쳐야 합니다.모두소스 경로그리고rsync"루트" 부분으로 간주하려는 소스 경로의 부분을 알려줍니다 . ./이 정보를 소스 경로의 원하는 위치에 삽입하여 제공 할 수 있습니다 .

귀하의 예에서 "루트" 부분은 바로 이므로 myroot/명령은 다음과 같습니다.

myroot/a/b/c$ rsync -R myroot/./a/b/c/myfile remoteroot

복잡한 상황에서 현재 디렉터리 경로 외부에 "루트" 부분을 지정하는 쉬운 방법을 원한다고 가정합니다.

강력하지만 비교적 간단한 방법은 경로 깊이 숫자를 이용하는 것입니다. 예를 들어 bash다음을 수행할 수 있습니다.

/path/to/myroot/a/b/c$ rsync -R "$(idx=4; IFS=/; set -- $PWD ; printf '%s/' "${@:1:idx}" . "${@:idx+1}")"/myfile remoteroot
                                 #     ^--- 4th piece of path counted as number of slashes in $PWD

물론 간결한 설명은 아니지만 명령 대체는 다음과 같이 파일 .bashrc에서 함수가 될 수 있습니다.

rootidx() {
    local idx="$1"

    # make Bash perform Word Splitting on / character
    local IFS=/ # make IFS local here, so to not affect global IFS

    # set function's arguments to each piece of current directory path,
    # as split on $IFS
    set -- $PWD

    # print from first argument up to the one indicated by wanted index,
    # then a ./, then from wanted index onwards
    printf '%s/' "${@:1:idx}" . "${@:idx+1}"
}

사용법은 다음과 같습니다:

/path/to/myroot/a/b/c$ rsync -R "$(rootidx 4)"/myfile remoteroot

또는 "루트"를 지정된 위치에 배치합니다.전체 경로의 경우 간단하고 POSIX 호환 방식은 다음과 같습니다.

/path/to/myroot/a/b/c$ rsync -R "${PWD%%/myroot/*}/myroot/./${PWD#*/myroot/}"/myfile remoteroot

매개변수 확장을 사용하여 $PWD현재 디렉토리 경로에 처음 나타나는 문자열을 삽입합니다 ./.myroot

그러나 매개변수 확장은 매우 간단하지만 매개변수를 지정할 때는 주의해야 합니다.일치하는 중간체그렇지 않으면 이 특정 확장은 예상대로 작동하지 않고 대신 전체 현재 디렉토리를 그 자체와 그 사이에 지정된 문자열과 연결합니다.

이 매개변수 확장은 함수로 만들어질 수도 있는데, 이는 함수를 더욱 강력하게 만드는 데 도움이 됩니다. 예를 들면 다음과 같습니다.

rootname() {
    [[ "$PWD" == */"$1"/* ]] && \  # check presence of string as intermediate path
        printf '%s' "${PWD%%/${1}/*}/${1}/./${PWD#*/${1}/}" || \  # apply the injection, or
        printf '%s -not valid-' "$1"   # try to produce an unlikely filename so to make `rsync` fail
}

사용법은 다음과 같습니다:

/path/to/myroot/a/b/c$ rsync -R "$(rootname myroot)"/myfile remoteroot

마지막으로, 경로 이름 확장을 이해하는 GNU 도구와 쉘이 있는 경우 **로컬 복사 작업에 이러한 기능을 사용할 수도 있습니다 cp. 예를 들어:

/path/to/myroot/a/b/c$ (shopt -s globstar; cd "$(rootidx 4)" && cp --parents **/myfile otherpath)

shopt -s globstar명령은 bash확장을 활성화합니다 **.

물론 이를 함수로 변환할 수도 있습니다.

smartcp() {
    # FIXME: some sanity checks over arguments here
    # TODO: detect type of first argument, and use either rootidx or rootname accordingly
    (shopt -s globstar; cd "$(rootidx "$1")" && cp --parents **/"${2}" "$3")
}

그래서:

/path/to/myroot/a/b/c$ smartcp 4 myfile otherpath

관련 정보