在包装器 bash 脚本中将通配符传递给 scp
Pass wildcard to scp in a wrapper bash script
我正在编写一个 bash 包装器,用于 scp 进出具有特定用户名的特定主机,例如:
johny@bonjour:~/bin$ cat scpphcl
#!/bin/bash
download=false
upload=false
local=""
remote=""
usage()
{
echo "Usage: [=11=] -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 包装器在本地文件名中传递通配符有什么帮助吗?
最好不要要求您的用户引用通配符模式。相反,我会更改程序的界面以在选项参数之后接受 任意数量 的本地路径:
echo "Usage: [=10=] [-d|-u] [-r <RemotePath>] <LocalPath>..."
读取选项时,使用 shift
:
while getopts "h?dur:" opt; do
case "$opt" in
h|\?)
usage
exit 0
;;
d)
download=true
upload=false
;;
u)
download=false
upload=true
;;
r)
remote="$OPTARG"
;;
*)
usage >&2
exit 1
;;
esac
done
shift $((OPTIND-1))
现在剩下的位置参数是本地文件名(可以用 "$@"
访问 - 注意那里的 all-important double-quotes):
if test -z "$*" # no LocalPath arguments!
then usage >&2; exit 1
elif $download
then exec scp somebody@somehost:"$remote" "$@"
elif $upload
then exec scp "$@" somebody@somehost:"$remote"
fi
我正在编写一个 bash 包装器,用于 scp 进出具有特定用户名的特定主机,例如:
johny@bonjour:~/bin$ cat scpphcl
#!/bin/bash
download=false
upload=false
local=""
remote=""
usage()
{
echo "Usage: [=11=] -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 包装器在本地文件名中传递通配符有什么帮助吗?
最好不要要求您的用户引用通配符模式。相反,我会更改程序的界面以在选项参数之后接受 任意数量 的本地路径:
echo "Usage: [=10=] [-d|-u] [-r <RemotePath>] <LocalPath>..."
读取选项时,使用 shift
:
while getopts "h?dur:" opt; do
case "$opt" in
h|\?)
usage
exit 0
;;
d)
download=true
upload=false
;;
u)
download=false
upload=true
;;
r)
remote="$OPTARG"
;;
*)
usage >&2
exit 1
;;
esac
done
shift $((OPTIND-1))
现在剩下的位置参数是本地文件名(可以用 "$@"
访问 - 注意那里的 all-important double-quotes):
if test -z "$*" # no LocalPath arguments!
then usage >&2; exit 1
elif $download
then exec scp somebody@somehost:"$remote" "$@"
elif $upload
then exec scp "$@" somebody@somehost:"$remote"
fi