5

So, I just started a new C++ class that requires me to program in a Linux environment. I don't have Linux installed on my machine, but I do have OS X and I can ssh into a linux machine in the lab at school (and this is preferable since my code must compile and run on the lab machine regardless of whether or not it works on my machine). If you can't tell by the end of this question, I am not incredibly familiar with Linux.

I will frequently need to take files that I download onto my local machine and put them on the remote machine, edit them to make the program, and then put them back onto my local machine to upload them to our dropbox. I got tired of typing
scp -P xx user@remote.host.com:~/filename filename
and decided to make an alias to do this. That's when I discovered aliases don't handle this kind of thing, so I decided to write a shell script instead. Here's what I've got:

#!/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"

Theoretically, I can just type get ~/path/to/filename and it will get the file from the remote host and copy it (with the same filename) into the current directory on the local machine.

That scp command, if run from the command line, works great. When I stick it in a shell script, it breaks. It gives me the error: No such file or directory

After a lot of testing (you can see some commented out debugging output up there) and researching, I found that the shell is expanding ~ before it sends it to the script (well, this is my guess based on what I found out about globs). My script is then looking for the file in the path of my local machine's home folder instead of the remote machine's home folder. How do I make it stop doing that?

I realized while typing this question that I probably just need some quotes when I run the command... but I really don't want to do that. Can I fix this somehow without having to type get "~/filename" because having to type those quotes is really annoying.

Sorry if there's a lot of extraneous info but I figured too much is better than too little. Thanks!

PS: I already found this about configuring ssh. While useful, I would still have to type the exact filename twice, which does not allow me to be as lazy as I want to be.

2
  • 1
    Small off-topic hint: switch to a version control system that allows you to simple git/svn/hg push/pull instead of scp-ing? Either of git, sv, mercurial should be installed on the remote machines?
    – Bernhard
    Aug 27, 2014 at 5:56
  • Small on-topic hint: For the synchronization script that I have (for data), I am consistent with folder, i.e. on my home system I have some <root1>/workdir and on the remote system <root2>/workdir, and I dynamically create the path-strings, so I don't have to pass any arguments.
    – Bernhard
    Aug 27, 2014 at 6:00

1 Answer 1

6

By default, scp remote paths are interpreted relative to the home directory, so you don't need the ~ at all:

scp user@remote.host.com:some/file/name filename

will download some/file/name from the home directory of user and save it as filename locally. When you want to use an absolute file path on the remote server, start it with /: scp host:/etc/passwd passwd.

Strictly, it's possible that your server is interpreting things differently. In that case, you could put ~ into your script, rather than repeating it on the command line every time (be as lazy as you want to be!):

scp user@remote.host.com:~/"$location" "$name"

That way your shell never gets the chance to interpret it. (It's also possible to quote the ~ on the command line: \~ or '~', but that's more work than necessary.) I imagine the first approach above will work, though.


Another note on the name variable. You say you want it to be just the base filename. There is a command for that exact purpose, the basename command:

name="$(basename "$location")"

That's simpler than running everything through sed.

3
  • Basename. I should have realized somebody already invented this.
    – Maribeth
    Aug 27, 2014 at 6:07
  • Also, now I'm getting another error : No such file or directory even though when I run scp with -v it looks like it is sending the correct path. This is true for both ways you mentioned, either omitting ~ completely or adding it to the script. Any ideas? EDIT: Using basename solved this, I guess my sed broke something when I moved that ~ around. Thank you!
    – Maribeth
    Aug 27, 2014 at 6:09
  • I'd suspect that the path really is wrong somewhere, but I can't tell without the commands in front of me. Aug 27, 2014 at 6:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .