scp bash 脚本的多个参数

scp multiple arguments of bash script

我正在尝试使用 scp 从远程服务器复制多个文件。

我可以成功地为单个参数做到这一点 script file_number

其中 script 是:

#!/bin/bash
echo Insert your username:
read user
scp $user@server:/path/run*.lz4 ./
lz4 -mdv --rm run*.lz4 

我所有的文件都采用以下格式:runXXXXsubY.lz4

这样我可以复制所有具有 XXXX==file_number 的文件,但我想传递多个参数,并复制所有这些文件,例如script 1 2 复制带有 xxxx==1XXXX==2 的所有文件。

我试过:

scp $user@server:/path/run"$@"*.lz4 ./ 

但是 $@ 在没有附加 *.lz4

的情况下得到扩展

我感谢任何在正确方向上的帮助。

谢谢

你最好的选择 IMO 是一个简单的 for 循环:

for xxx; do
    scp "$user@server:/path/run${xxx}.lz4" ./ 
done

如果您确实想要 运行 一个 scp(避免多次密码提示不是这样做的动机;避免多次密码提示的方法是设置您的 ssh 密钥,这样就不会密码是必需的),你可以使用 xargs:

printf "$user@server:/path/run%s.lz4[=11=]" "$@" | xargs -0 -J % scp % ./

这不保证单次调用,并且 xargs 将 运行 多次调用 scp 如果传递了足够多的 args 参数字符串超过特定限制,但这可能应该足够了。

基本问题是,当 shell 扩展 $user@server:/path/run"$@"*.lz4 时,它不会为每个参数复制 $user:...*.lz4 部分,它只是有点盲目地将参数列表(包括参数之间的分词符)添加到中间。因此,如果参数是 12,它实际上扩展为:

scp $user@server:/path/run"1" "2"*.lz4 ./ 

...所以 $user@server:/path/run"1""2"*.lz4scp 的单独参数,这没有用。您可以做的是根据参数创建一个数组,然后使用 that 作为 scp 的源列表。像这样:

sources=()
for runNum in "$@"; do
    sources+=("$user@server:/path/run${runNum}*.lz4")
done
scp "${sources[@]}" ./

然后为 lz4 命令使用单独的循环:

for runNum in "$@"; do
    lz4 -mdv --rm run${runNum}*.lz4
done

编辑:为避免必须多次进行身份验证,您可以打开主 SSH 连接并让所有 scp 传输搭载在该连接上。这是一个示例,主要基于 Felix Rabe 的回答 here:

# Create the array of source file patterns to fetch
sources=()
for runNum in "$@"; do
    sources+=("$user@server:/path/run${runNum}*.lz4")
done

# Open master SSH connection:
# (This is the only time you have to enter the password)
sshSocket=~/"$user@server"
ssh -M -f -N -S "$sshSocket" "$user@server"

# Actually copy the files:
scp -o ControlPath="$sshSocket" "${sources[@]}" ./

# Close master connection:
ssh -S "$sshSocket" -O exit "$user@server"

为远程文件名构建模式的一个参数替换想法:

$ fn="$@"
$ echo scp "user@server:/path/run{${fn// /,}}*.lz4" ./

假设 $@ = 222 333 这会生成:

scp user@server:/path/run{222,333}*.lz4 ./

注意: 一旦对格式感到满意,删除 echo