Andrew Mercer

OpenSSH File Transfer & Remote Commands

Covers scp, tar-over-SSH piping, sshfs, and running one-off remote commands. For interactive sessions and port forwarding, see openssh-port-forwarding.md.


1. scp

# Paths with spaces — quote the remote side
scp 'user@host:~/path/to/file with spaces.txt' .

scp's legacy protocol implementation has been deprecated upstream in favor of the SFTP protocol under the hood (recent OpenSSH scp uses SFTP by default). For anything beyond simple one-off copies, prefer sftp or rsync -e ssh, both of which handle partial transfers, resuming, and large directory trees more robustly.

2. sshfs — mount a remote directory over SSH

# Install
sudo dnf install fuse-sshfs        # RHEL/Fedora
sudo apt install sshfs             # Debian/Ubuntu

# Mount
sshfs user@remote-server:/home/user/dir/ ./local-mount-dir/

# Unmount
fusermount -u ./local-mount-dir/

Persistent mount via /etc/fstab:

# /etc/fstab
user@remote-host:/path/to/remote_dir/ /path/to/local_dir/ fuse.sshfs defaults 0 0

For unattended mounts (boot-time, no interactive passphrase prompt), use a dedicated key with no passphrase loaded via IdentityFile in ~/.ssh/config for that host, scoped as tightly as possible on the remote side (see the authorized_keys forced-command pattern in openssh-comprehensive-guide.md §4.4).

3. Streaming tar over SSH

Faster than scp for large directory trees with many small files, since it avoids per-file protocol overhead — pipes a tar stream directly through the SSH channel.

Push a directory to a remote host:

tar czf - dir/ | ssh user@remote-host tar xzf - -C ~/

Pull a directory from a remote host:

ssh user@remote-host "tar czf - directory_to_get" | tar xzvf - -C path_to_put

Push a single file, leaving it compressed on the far end:

tar czvf - catalina.out | ssh user@remote-host 'cat - > catalina.out.gz'

Push a single file, decompressed on the far end:

tar czvf - catalina.out | ssh user@remote-host 'tar xzf -'

Copy between two remote hosts, via your local machine as the relay:

ssh user@source-host 'tar jcf - /path/to/data' | tar xjf -

(-j is bzip2; swap for -z/gzip as needed — same piping pattern either way.)

These patterns predate rsync being universally available. rsync -avz -e ssh source/ user@host:dest/ is usually the better tool now — it gets you resumability and delta transfers for free. Reach for raw tar-over-SSH mainly when rsync genuinely isn't installed on one end (minimal containers, embedded systems) or you specifically want a one-shot stream with no intermediate state.

4. One-off remote commands

# Force a pseudo-tty (needed for interactive/screen-based remote programs)
ssh -t remote-host "cd /some/dir; bash"

# Simple command execution
ssh user@host 'mkdir ~/new_dir'
ssh user@host 'df -h'

-t forces pty allocation — required when the remote command expects an interactive terminal (an editor, a menu-driven tool, or — as above — dropping into an interactive shell after a cd).

5. Backups over SSH

MySQL dump, compressed in transit:

mysqldump your_db | gzip -c | ssh user@remote-host 'cat > /path/to/db_backup.sql.gz'

Relay a remote command's output to a second remote host (e.g. copying a file listing off an ESXi host you can't scp from directly):

ssh root@esxi-host 'ls /vmfs/volumes/<datastore-uuid>/backup-dir' | ssh user@archive-host 'cat > /path/to/files.txt'

Same pattern generalizes to piping an actual tar backup stream between two remote hosts instead of just a file listing.