scp
파일을 복사하는 데 사용할 수 있는 표현식을 구성하는 방법이 있나요?
file-name-version-1.2.1.jar
파일을 복사할 필요가 없습니다.
file-name-version-1.2.1-sources.jar
file-name-version-1.2.1-javadoc.jar
하지만 정확한 버전 번호를 모르시나요? file-name-version-*.*.*.jar
명백한 이유로 작동하지 않습니다. 나는 다음과 같은 구문을 찾고 있습니다.
file-name-version-\d.\d.\d.jar
또는 그런 것.
답변1
기억해야 할 한 가지는 파일 이름이 전달된다는 것입니다.수정되지 않은원격 사용자의 로그인 쉘로.
이렇게 하면:
scp user@remote-machine:'something' ...
원격 시스템에서는 sshd
다음 로그인 셸이 실행됩니다 user
.
that-shell -c 'scp -f something'
그 안의 패턴을 확장하는 것이 바로 이 껍질입니다.
즉, 패턴 확장 방법은 원격 사용자가 사용하는 로그인 셸에 따라 달라집니다. 해당 쉘이 이면 bash
사용자가 ~/.bashrc
이나 에 무엇을 가지고 있는지에 따라 달라집니다 /etc/bash.bashrc
(예: bash-completion
설치 시 거기에서 호출하면 ksh 스타일 확장 와일드카드가 켜집니다). 호출할 때 어떤 이유로든 bash
이러한 내용을 읽기 때문 ssh
입니다(비록 이것이 대화형 쉘).
이는 또한 something
이것이 사실 이라면 'blah; rm -rf "$HOME"'
비참한 결과를 초래할 것임을 의미합니다.
이것은 설계 오류 중 하나입니다 ssh
.
something
특정 셸을 강제로 파일 목록으로 확장하려면 다음 방법을 사용할 수 있습니다.
LC_SCPFILES=something scp -o SendEnv=LC_SCPFILES "localhost:</dev/null
bash -O extglob -c 'exec scp -f -- \$LC_SCPFILES';exit" /dest/dir
원격 사용자의 로그인 셸이 일반 Unix 셸(적어도 Bourne, csh, rc 또는 Fish 제품군)이고 bash
여기에 설치되어 있고 sshd
에 이름을 전달할 수 있는 경우 에만 해당됩니다 LC_
.
요령은 대부분의 sshd
배포에서 이름이 다음으로 시작하는 환경 변수 전달을 허용한다는 LC_
것입니다. 이는 스페인어를 사용하는 사용자가 원격 시스템의 기본 언어나 원격 사용자의 언어 대신 스페인어로 된 원격 명령에서 오류 메시지를 받을 수 있도록 하기 위해 필요합니다. )) .
여기서는 환경 변수를 전달 something
합니다 LC_SCPFILES
.
원격 시스템에서 다음을 sshd
실행합니다.
that-shell -c 'scp -f </dev/null
bash -O extglob -c '\''exec scp -f -- $LC_SCPFILES'\'';exit'
/dev/null
첫 번째 것은 표준 입력이 에서 리디렉션되기 때문에 scp
즉시 종료됩니다 . 그런 다음 옵션을 사용하여 선택한 셸을 시작하고( bash
) 해석을 위해 명령줄을 extglob
사용합니다 .exec scp -f -- $LC_SCPFILES
하위 프로세스 ( 나중에 추가하여 강제 실행) bash
에서 실행되기 때문에 소스는 제공되지 않으므로 기본 동작을 기대할 수 있습니다 ( 시작 시 또는 환경 변수가 어떻게든 설정되지 않는 한).that-shell
;exit
bash
~/.bashrc
bash
that-shell
BASHOPTS
SHELLOPTS
BASH_ENV
따옴표가 없기 때문에 $LC_SCPFILES
토큰화 및 파일명 생성(와일드카드)의 영향을 받지만 다른 셸 확장의 영향을 받지 않으며 포함된다고 rm -rf "$HOME"
해서 something
유사한 작업을 수행 하지 않습니다.
이제 패턴이 원격 시스템에서 확장되었는지 확인했으므로 bash -O extglob
확장된 glob 연산자(여기서 도우미 함수 사용)를 사용하여 패턴을 일치시키는 데 사용할 수 있습니다.
safer_scp() (
file=$1; shift
export LC_SCPFILES="${file#*:}"
exec scp -o SendEnv=LC_SCPFILES "${file%%:*}:</dev/null
bash -O extglob -c 'exec scp -f -- \$LC_SCPFILES';exit" "$@"
)
safer_scp user@host:'file-name-version-+([0-9]).+([0-9]).+([0-9]).jar' .
on 을 사용하면 +([0-9])
하나 이상의 소수 자릿수와 일치합니다. 예를 들어 위의 패턴은 일치합니다.extglob
bash
file-name-version-1.2.3.jar
file-name-version-12.123.1234.jar
( safer_scp
위에서는 첫 번째 인수가 이고 또는 같은 것은 작동하지 않는다고 가정합니다 host:file-patterns
. 를 safer_scp -r ...
사용 safer_scp host1:f1 host2:f2 ...
하려는 경우 -r
가장 쉬운 방법은 위의 인수를 로 바꾸는 safer_scp_r
함수 를 정의하는 것입니다 .)scp -f
scp -r -f
IFS=;
위에 단어 분리를 추가하면 단어 분리를 비활성화할 수 있습니다 exec scp...
.
또한 모든 GNU 시스템에 설치되어 있기 때문에 여기에서 사용하고 있지만 원격 시스템에 설치되어 있다는 것을 bash
알고 있다면 다음을 사용할 수 있습니다.zsh
zsh -o extendedglob -o globsust
zsh
대신 와일드카드 (재귀, 한정자...) 의 모든 기능을 활용하세요.
( -o shwordsplit
단어 분할도 원할 경우 추가).
예를 들어:
safer_scp() (
file=$1; shift
export LC_SCPFILES="${file#*:}"
exec scp -o SendEnv=LC_SCPFILES "${file%%:*}:</dev/null
zsh -o extendedglob -o globsubst -c 'exec scp -f -- \$LC_SCPFILES';exit" "$@"
)
safer_scp user@host:'file-name-version-<->(.<->)#.jar' .
은 (는) 에서 까지의 임의의 십진 정수 file-name-version-1.jar
이고 , 정규식 연산자와 같은 임의의 십진 정수입니다(0개 이상의 선행 원자).file-name-version-1.2.3.4.5.jar
<x-y>
x
y
<->
#
*
답변2
이 특별한 경우에는
scp 'user@host:file-name-version-*[0-9].jar' .
그 정도면 충분할 것입니다.
답변3
내 생각엔 네가 원하는 것 같아
file-name-version-[0-9].[0-9].[0-9].jar
답변4
유연성을 위해 다음을 사용하세요.동기화SCP 대신.
rsync --include='file-name-*.jar' \
--exclude='*-sources.jar' --exclude='*-javadoc.jar' \
example.com:/some/directory/ local/directory/