0

I want to copy all files including "hidden" . files from a directory output to a remote directory target using scp. Alternatives welcome except rsync. Unfortunately the hosting provider won't allow its installation.

I have looked up several solutions and it seems harder than what I expected.


scp -P 22 -r path/to/output/ "$USER@$HOST:/path/target/"

and

scp -P 22 -r path/to/output "$USER@$HOST:/path/target/"

put files to /path/target/output/ or requires renaming.


scp -P 22 -r path/to/output/* "$USER@$HOST:/path/target/"

This does not match hidden files.


scp -P 22 -r path/to/output/. "$USER@$HOST:/path/target/"

This no longer works (details in comment to https://unix.stackexchange.com/a/232947 ).


scp -P 22 -r path/to/output/{,.[!.],..?}* "$USER@$HOST:/path/target/"

This will fail in case not all patterns have a match (e.g. missing files of the form .<filename>.


I am looking for a way to just copy all contents of a directory recursively to a remote directory. I have SSH or FTP access. Bonus would be to clean the target dir before copying.

Edit: leaving the trailing slash for target has no impact

2 Answers2

1

You can use bash's nullglob option to skip unmatched wildcards:

shopt -s nullglob
scp -P 22 -r path/to/output/{,.[!.],..?}* "$USER@$HOST:/path/target/"
shopt -u nullglob    # Put it back to normal afterward!

One possible problem with this is that if the directory is entirely empty (i.e. none of the wildcard branches match anything), the entire argument vanishes and scp complains because you didn't give it both a source and a target. If this is possible, store the file list in an array and check for contents first:

shopt -s nullglob
filesToSend=( path/to/output/{,.[!.],..?}* )
shopt -u nullglob    # Put it back to normal afterward!
if (( ${#filesToSend[@]} > 0 )); then
    scp -P 22 -r "${filesToSend[@]}" "$USER@$HOST:/path/target/"
else
    echo "No files in source directory" >&2
fi
1

I am using a solution found here that uses ssh and tar:

tar -C path/to/output/ -cf - . | ssh $USER@$HOST tar -C path/target/ -xvf -

This tells tar to change to path/to/output/ archive to - (std) and include all (.) files then pipes it to unpack to remote where tar changes to the target output dir before unpacking.