저는 두 대의 컴퓨터에 큰 파일 시스템 트리를 유지 관리하고 있으며 종종 한 컴퓨터에서 다른 컴퓨터로 하나 또는 몇 개의 파일을 복사해야 합니다.
길고 동일한 경로를 입력하지 않고도 두 트리의 동일한 위치 간에 자동으로 복사할 수 있습니까?
예를 들어, 를 지정하지 않고 myroot/a/b/c
파일을 복사하고 싶습니다 .remoteroot/a/b/c
a/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