Skip to content

Instantly share code, notes, and snippets.

@glowinthedark
Last active February 9, 2024 20:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save glowinthedark/e56fed33be889cea6ec2326dc33f535d to your computer and use it in GitHub Desktop.
Save glowinthedark/e56fed33be889cea6ec2326dc33f535d to your computer and use it in GitHub Desktop.
Copy folders between local <=> SSH remote using tar piped over SSH using scp syntax like: `scp-turbo.sh myremote:/etc/apache2 /tmp/mylocal/dir`
#!/usr/bin/env bash
# URL: https://gist.github.com/glowinthedark/e56fed33be889cea6ec2326dc33f535d
# uses scp syntax e.g.:
#
# REMOTE -> LOCAL (folder to folder)
# scp-turbo.sh myremote:/etc/apache2 /tmp/mylocal/dir
# REMOTE -> LOCAL (folder to .gz)
# scp-turbo.sh myremote:/etc/apache2 backup.gz
# LOCAL -> REMOTE (folder to folder)
# scp-turbo.sh /tmp/mylocal/dir myremote:/home/user32/
# LOCAL -> REMOTE (folder to .gz)
# scp-turbo.sh /tmp/mylocal/dir myremote:/tmp/backup.gz
#
# Based on:
# - https://cromwell-intl.com/open-source/tar-and-ssh.html
# - https://www.cyberciti.biz/faq/howto-use-tar-command-through-network-over-ssh-session/
if [[ $# -eq 0 ]]; then
printf "USAGE:\n\t${0##*/} <source> <destination>\n\n"
echo "NOTE: Source and destination can be in the format host:path or just path"
exit 1
fi
source=$1
dest=$2
# https://unix.stackexchange.com/questions/353845/using-a-variable-with-rename-command
# copying FROM a remote
if [[ $source == *:* ]]; then
source_host=${source%%:*}
source_path=${source#*:}
else
source_host=""
source_path=$source
fi
# copying TO a remote
if [[ $dest == *:* ]]; then
dest_host=${dest%%:*}
dest_path=${dest#*:}
else
dest_host=""
dest_path=$dest
fi
echo SOURCE_HOST: "$source_host"
echo SOURCE_PATH: "$source_path"
echo
echo DEST_HOST: "$dest_host"
echo DEST_PATH: "$dest_path"
read -p "Press any key to start copying..." -n 1 -s
# REMOTE -> LOCAL
if [[ -z "$dest_host"
&& -n "$source_host"
&& -n "$source_path"
&& -n "$dest_path"
]]; then
# if the destination ends with .gz then create a .gz archive (no unpacking)
if [[ "$dest_path" =~ \.(tgz|gz)$ ]]; then
ssh "$source_host" tar --ignore-failed-read -czvf - -C "$source_path" . > "${dest_path}"
else
# create destination folder from source
dest_dir="${dest_path%/}/$(basename $source_path)"
mkdir -p "$dest_path/$dest_dir"
ssh "$source_host" tar --ignore-failed-read -czvf - -C "$source_path" . | tar xzvf - -C "${dest_dir}"
echo "Done!"
exit 0
fi
fi
# LOCAL -> REMOTE
if [[ -z "$source_host"
&& -n "$source_path"
&& -n "$dest_host"
&& -n "$dest_path"
]]; then
# if the remote destination ends with .gz then create a remote .gz archive (no unpacking)
if [[ "$dest_path" =~ \.(tgz|gz)$ ]]; then
COPYFILE_DISABLE=1 tar --exclude='.DS_Store' -czvf - -C "${source_path}" . | ssh "$dest_host" "cat > $dest_path"
else
# create destination folder from source
dest_dir="${dest_path%/}/$(basename $source_path)"
ssh "$dest_host" mkdir -p "$dest_dir"
COPYFILE_DISABLE=1 tar --exclude='**/.DS_Store/*' --exclude='**/._*' --exclude='._*' -cvf - -C "${source_path}" . | ssh "$dest_host" "tar -xvf - -C $dest_dir"
fi
echo "Done!"
exit 0
fi
# Example to extract local tar at remote over ssh:
# tar -czf - /etc/apache2 | ssh arh "tar -xzf - -C /tmp/gen"
# excluding files with tar: https://stackoverflow.com/questions/984204/shell-command-to-tar-directory-excluding-certain-files-folders
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment