How to filter files when using scp to copy dir recursively?

I'd probably recommend using something like rsync for this due to its include and exclude flags, e.g:-

rsync -rav -e ssh --include '*/' --include='*.class' --exclude='*' \
server:/usr/some/unknown/number/of/sub/folders/ \ 
/usr/project/backup/some/unknown/number/of/sub/folders/

Some other useful flags:

  • -r for recursive
  • -a for archive (mostly all files)
  • -v for verbose output
  • -e to specify ssh instead of the default (which should be ssh, actually)

To exclude dotfiles in base directory:

scp -r [!.]* server:/path/to/something

[!.]* is a shell glob that expands to all files in working directory not starting with a dot.


There is no feature in scp to filter files. For "advanced" stuff like this, I recommend using rsync:

rsync -av --exclude '*.svn' user@server:/my/dir .

(this line copy rsync from distant folder to current one)

Recent versions of rsync tunnel over an ssh connection automatically by default.


Since you can scp you should be ok to ssh,
either script the following or login and execute...

# After reaching the server of interest
cd /usr/some/unknown/number/of/sub/folders
tar cfj pack.tar.bz2 $(find . -type f -name *.class)

return back (logout) to local server and scp,

# from the local machine
cd /usr/project/backup/some/unknown/number/of/sub/folders
scp you@server:/usr/some/unknown/number/of/sub/folders/pack.tar.bz2 .
tar xfj pack.tar.bz2

If you find the $(find ...) is too long for your tar change to,

find . -type f -name *.class | xargs tar cfj pack.tar.bz2

Finally, since you are keeping it in /usr/project/backup/,
why bother extraction? Just keep the tar.bz2, with maybe a date+time stamp.