scp 过早解释波浪号 (~) 的 Bash 脚本

Mar*_*eth 4 bash scp shell-script quoting home

所以,我刚刚开始了一个新的 C++ 类,它要求我在 Linux 环境中进行编程。我的机器上没有安装 Linux,但我有 OS X,我可以在学校实验室的 linux 机器上使用 ssh(这是可取的,因为我的代码必须在实验室机器上编译和运行,无论是否不适用于我的机器)。如果你在这个问题的结尾还说不清楚,我对 Linux 并不是非常熟悉。

我经常需要将我下载到本地机器上的文件放在远程机器上,编辑它们以制作程序,然后将它们放回我的本地机器上以将它们上传到我们的保管箱。我厌倦了打字
scp -P xx user@remote.host.com:~/filename filename
,决定做一个别名来做到这一点。那时我发现别名不能处理这种事情,所以我决定写一个 shell 脚本来代替。这是我所拥有的:

#!/bin/bash

# Author: me
# Created 26 August 2014
# transfers a file from remote machine to current directory in local machine
# keeps same filename

location="$1"
# name gets just the part of the path after the last slash
# ie the filename
name="$(echo "$1" | sed -n -e 's/^.*\///p')"
# echo "$location"
# echo "$name"
scp -P xx user@remote.host.com:"$location" "$name"
Run Code Online (Sandbox Code Playgroud)

理论上,我只需键入get ~/path/to/filename,它就会从远程主机获取文件并将其(具有相同的文件名)复制到本地计算机上的当前目录中。

该 scp 命令,如果从命令行运行,效果很好。当我将它粘贴在 shell 脚本中时,它会中断。它给了我错误:No such file or directory

经过大量测试(您可以在那里看到一些注释掉的调试输出)和研究,我发现 shell 在将其发送到脚本~ 之前正在扩展(好吧,这是我根据我对 globs 的发现而得出的猜测) . 我的脚本然后在我本地机器的主文件夹而不是远程机器的主文件夹的路径中查找文件。我如何让它停止这样做?

我在输入这个问题时意识到,当我运行命令时我可能只需要一些引号......但我真的不想这样做。我可以以某种方式解决这个问题而不必输入,get "~/filename"因为必须输入这些引号真的很烦人。

对不起,如果有很多无关的信息,但我认为太多总比太少好。谢谢!

PS:我已经找到有关配置 ssh 的内容。虽然很有用,但我仍然需要输入两次确切的文件名,这不允许我像我想的那样懒惰。

Mic*_*mer 6

默认情况下,scp远程路径是相对于主目录解释的,因此您根本不需要~

scp user@remote.host.com:some/file/name filename
Run Code Online (Sandbox Code Playgroud)

some/file/name将从 的主目录下载user并将其保存为filename本地。如果要在远程服务器上使用绝对文件路径,请以/:开头scp host:/etc/passwd passwd

严格来说,您的服务器可能会以不同的方式解释事物。在这种情况下,您可以将其~放入脚本中,而不是每次都在命令行上重复它(随心所欲!):

scp user@remote.host.com:~/"$location" "$name"
Run Code Online (Sandbox Code Playgroud)

这样你的 shell 就永远没有机会解释它。(也有可能引述~在命令行上:\~'~',但是这比必要更多的工作。)我想上面会工作的第一种方法,虽然。


关于name变量的另一个注释。您说您希望它只是基本文件名。有一个用于该确切目的的basename命令命令

name="$(basename "$location")"
Run Code Online (Sandbox Code Playgroud)

这比通过sed.