SCP 파일 패턴에서 문자 제외

SCP 파일 패턴에서 문자 제외

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;exitbash~/.bashrcbashthat-shellBASHOPTSSHELLOPTSBASH_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])하나 이상의 소수 자릿수와 일치합니다. 예를 들어 위의 패턴은 일치합니다.extglobbashfile-name-version-1.2.3.jarfile-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 -fscp -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>xy<->#*

답변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/

관련 정보