【发布时间】:2018-02-27 15:14:05
【问题描述】:
我正在编写一个 bash 包装器,用于 scp'ing 进出具有特定用户名的特定主机,例如:
johny@bonjour:~/bin$ cat scpphcl
#!/bin/bash
download=false
upload=false
local=""
remote=""
usage()
{
echo "Usage: $0 -d[-u] -l <LocalPath> -r <RemotePath>"
exit 1
}
while getopts "h?dul:r:" opt; do
case "$opt" in
h|\?)
usage
;;
d)
download=true
upload=false
;;
u)
download=false
upload=true
;;
l)
local=$OPTARG
;;
r)
remote=$OPTARG
;;
esac
done
if [[ -z $local || -z $remote ]]; then
echo "Need to provide local and remote path."
usage
fi
if $download; then
scp somebody@somehost:"$remote" $local
elif $upload; then
scp $local somebody@somehost:"$remote"
else
echo "Neither download nor upload?"
exit 1
fi
if [[ $? -ne 0 ]]; then
echo "Something wrong happened in the scp process."
exit 1
fi
exit 0
它适用于通常的文件名,但如果本地文件名字段中有任何通配符,它将无法正常工作。
johny@bonjour:~/test$ scpphcl -u -l * -r /u/somebody/temp
Need to provide local and remote path.
Usage: /Users/johny/bin/scpphcl -d[-u] -l <LocalPath> -r <RemotePath>
有一个解决方法,如果其中有通配符,则在本地文件参数周围使用单引号:
johny@bonjour:~/test$ scpphcl -u -l '*' -r /u/somebody/temp
但是,如果在文件夹 test 之外发出命令,即使这种解决方法也不起作用:
johny@bonjour:~/test$ cd ..
johny@bonjour:~$ scpphcl -u -l 'test/*' -r /u/somebody/temp
这不起作用,会挂在 scp 进程中。
对如何使用 bash 包装器在本地文件名中传递通配符有任何帮助吗?
【问题讨论】:
-
您可能需要转义通配符以使其远程扩展而不在本地
-
@Inian
scpphcl -u -l 'test/\*' -r /u/somebody/temp和scpphcl -u -l test/\* -r /u/somebody/temp都不起作用。 -
您也需要引用
"$OPTARG"(因此)。还有"$local"和"$remote"。只要正确引用,无处不在。实际上,你想要local=($OPTARG),然后在命令中使用"${local[@]}"。但可以叫它别的名字——local是一个 Bash 关键字。 -
@TobySpeight 非常感谢你,托比。有用。另外,感谢您建议为本地路径指定
local以外的名称。我不知道这是一个 bash 关键字。您能否将您的评论放入答案部分,以便我将其标记为解决方案?如果您添加一些解释会更好。我猜localfile=($OPTARG)可能将通配符扩展视为一个数组。后来在scp命令中使用的时候,是${localfile[@]}这个数组解引用的方式吗? -
是的,这是一个数组。扩展数组的方式是
"${localfile[@]}"(那些双引号很重要!)。
标签: bash scp wildcard-expansion