有没有办法建立一个表达式scp
,我可以用它来复制文件
file-name-version-1.2.1.jar
Run Code Online (Sandbox Code Playgroud)
不复制文件
file-name-version-1.2.1-sources.jar
file-name-version-1.2.1-javadoc.jar
Run Code Online (Sandbox Code Playgroud)
虽然不知道确切的版本号?file-name-version-*.*.*.jar
由于明显的原因将不起作用。我正在寻找类似的语法
file-name-version-\d.\d.\d.jar
Run Code Online (Sandbox Code Playgroud)
或类似的东西。
要记住的一件事是文件名未经修改地传递给远程用户的登录 shell。
如果你这样做:
scp user@remote-machine:'something' ...
Run Code Online (Sandbox Code Playgroud)
在远程机器上,sshd
将运行user
as的登录 shell :
that-shell -c 'scp -f something'
Run Code Online (Sandbox Code Playgroud)
正是那个外壳将扩展那里的模式。
这意味着模式的扩展方式将取决于远程用户使用的登录 shell。当那个 shell 是 时bash
,这也将取决于用户在他的 中~/.bashrc
有什么,或者有什么/etc/bash.bashrc
(例如bash-completion
,当安装时从那里调用,打开 ksh 风格的扩展通配符),因为出于某种原因,bash
在调用时读取那些ssh
(即使那不是交互式外壳)。
这也意味着something
,例如'blah; rm -rf "$HOME"'
,如果是,那将产生灾难性的后果。
这是错误的设计之一 ssh
.
如果要强制特定的 shell 将其扩展something
为文件列表,可以使用以下技巧:
LC_SCPFILES=something scp -o SendEnv=LC_SCPFILES "localhost:</dev/null
bash -O extglob -c 'exec scp -f -- \$LC_SCPFILES';exit" /dest/dir
Run Code Online (Sandbox Code Playgroud)
只有当远程用户的登录 shell 是一个普通的 Unix shell(至少是 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'
Run Code Online (Sandbox Code Playgroud)
因为它的标准输入是从 重定向的/dev/null
,第一个scp
将立即退出。然后我们启动我们选择的 shell ( bash
),使用extglob
选项,并使用exec scp -f -- $LC_SCPFILES
命令行来解释。
由于bash
将在一个子进程中运行that-shell
(这是我们加入了强制执行;exit
后),bash
将不获取的~/.bashrc
,所以我们可以预期的默认行为bash
存在(除非以某种方式that-shell
,在启动时,设置BASHOPTS
,SHELLOPTS
或BASH_ENV
环境变量)。
因为$LC_SCPFILES
没有被引用,它会受到分词和文件名生成(通配)的影响,但不会受到其他 shell 扩展的影响,并且不会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' .
Run Code Online (Sandbox Code Playgroud)
的+([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...
上述之前添加 a 来禁用分词。
还要注意,我们在bash
这里使用的基础是它安装在所有 GNU 系统上,但是如果您知道zsh
安装在远程系统上,则可以使用
zsh -o extendedglob -o globsust
Run Code Online (Sandbox Code Playgroud)
而是从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' .
Run Code Online (Sandbox Code Playgroud)
将复制file-name-version-1.jar
and file-name-version-1.2.3.4.5.jar
(<x-y>
是从x
to的任何十进制整数y
,<->
是任何十进制整数,#
就像正则*
表达式运算符(前面的原子的 0 个或多个))
归档时间: |
|
查看次数: |
1936 次 |
最近记录: |