Several times throughout the day, I may be running a test where I need to look through a log file on a remote server. I've gotten used to using my terminal to sftp
into the remote server and pull the desired log file down to /tmp
on my local machine.
I was looking through the options today using man sftp
in an attempt to figure out a way to run the following commands basically in a single line so that I don't have to type a command, press enter, type a command press enter, etc.
(what I do now)
sftp myuser@myserver
--mypassword at prompt
lcd /tmp
get /dir/dir/dir/dir/file
quit
I found while looking through man sftp
a reference to scp
which I haven't used before. I feel it may be what I'm looking for, but I didn't see a way to specify where I wanted the securely copied file to go.
Could someone provide me with a way to get /dir/file
from a remote server and have it download to /tmp/file_plus-my-description
?
I was hoping to be able to run an sftp or scp command similar to a regularUNIX copy like:
scp myuser@myserver /dir/file /tmp/file_plus-my-description
I'm using the built in Terminal
in Mac OS X 10.8. Thanks.
Update Sep 2017 - tl;dr
Download a single file from a remote ftp server to your machine:
sftp {user}@{host}:{remoteFileName} {localFileName}
Upload a single file from your machine to a remote ftp server:
sftp {user}@{host}:{remote_dir} <<< $'put {local_file_path}'
Original answer:
Ok, so I feel a little dumb. But I figured it out. I almost had it at the top with:
sftp user@host remoteFile localFile
The only documentation shown in the terminal is this:
sftp [user@]host[:file ...]
sftp [user@]host[:dir[/]]
However, I came across this site which shows the following under the synopsis:
sftp [-vC1 ] [-b batchfile ] [-o ssh_option ] [-s subsystem | sftp_server ] [-B buffer_size ] [-F ssh_config ] [-P sftp_server path ] [-R num_requests ] [-S program ] host
sftp [[user@]host[:file [file]]]
sftp [[user@]host[:dir[/]]]
So the simple answer is you just do :
after your user and host then the remote file and local filename. Incredibly simple!
Single line, sftp copy remote file:
sftp username@hostname:remoteFileName localFileName
sftp kyle@kylesserver:/tmp/myLogFile.log /tmp/fileNameToUseLocally.log
Update Feb 2016
In case anyone is looking for the command to do the reverse of this and push a file from your local computer to a remote server in one single line sftp
command, user @Thariama below posted the solution to accomplish that. Hat tip to them for the extra code.
sftp {user}@{host}:{remote_dir} <<< $'put {local_file_path}'
SCP answer
The OP mentioned SCP, so here's that.
As others have pointed out, SFTP is a confusing since the upload syntax is completely different from the download syntax. It gets marginally easier to remember if you use the same form:
echo 'put LOCALPATH REMOTEPATH' | sftp USER@HOST
echo 'get REMOTEPATH LOCALPATH' | sftp USER@HOST
In reality, this is still a mess, and is why people still use "outdated" commands such as SCP:
scp USER@HOST:REMOTEPATH LOCALPATH
scp LOCALPATH USER@HOST:REMOTEPATH
SCP is secure but dated. It has some bugs that will never be fixed, namely crashing if the server's .bash_profile
emits a message. However, in terms of usability, the devs were years ahead.
To UPLOAD a single file, you will need to create a bash script. Something like the following should work on OS X if you have sshpass
installed.
Usage:
sftpx <password> <user@hostname> <localfile> <remotefile>
Put this script somewhere in your path and call it sftpx
:
#!/bin/bash
export RND=`cat /dev/urandom | env LC_CTYPE=C tr -cd 'a-f0-9' | head -c 32`
export TMPDIR=/tmp/$RND
export FILENAME=$(basename "$4")
export DSTDIR=$(dirname "$4")
mkdir $TMPDIR
cp "$3" $TMPDIR/$FILENAME
export SSHPASS=$1
sshpass -e sftp -oBatchMode=no -b - $2 << !
lcd $TMPDIR
cd $DSTDIR
put $FILENAME
bye
!
rm $TMPDIR/$FILENAME
rmdir $TMPDIR
Or echo 'put {path to file}' | sftp {user}@{host}:{dir}
, which would work in both unix and powershell.
sftp supports batch files.
From the man page:
-b batchfile
Batch mode reads a series of commands from an input batchfile instead of stdin.
Since it lacks user interaction it should be used in conjunction with non-interactive
authentication. A batchfile of `-' may be used to indicate standard input. sftp
will abort if any of the following commands fail: get, put, rename, ln, rm, mkdir,
chdir, ls, lchdir, chmod, chown, chgrp, lpwd, df, symlink, and lmkdir. Termination
on error can be suppressed on a command by command basis by prefixing the command
with a `-' character (for example, -rm /tmp/blah*).
--batch
would require me to put my commands into a file then pass in that file as a param. I'm still playing with scp
, I feel it may contain my solution.
OpenSSH scp
supports SFTP protocol since 8.7.
Since OpenSSH 9.0 the scp
uses SFTP by default.
In 8.7 through 8.9, the SFTP has to be selected via -s
parameter.
Download:
scp -s user@host:/remote/source/path /local/target/path
Upload:
scp -s /local/source/path user@host:/remote/target/path
A minor modification like below worked for me when using it from within perl and system() call:
sftp {user}@{host} <<< $'put {local_file_path} {remote_file_path}'
Success story sharing
sftp {user}@{host}:{dir} <<< $'cd web\n put my_file.txt'