83

I often use SCP to copy files around - particularly web-related files. The problem is that whenever I do this, I can't get my command to copy hidden files (eg, .htaccess).

I typically invoke this:

scp -rp src/ user@server:dest/

This doesn't copy hidden files. I don't want to have to invoke this again (by doing something like scp -rp src/.* ... - and that has strange . and .. implications anyway.

I didn't see anything in the scp man page about an "include hidden files".

How can I accomplish this?

1
  • I assume that src/.* also copies src/.. (the parent directory), right?
    – Ken Sharp
    Dec 18, 2015 at 13:34

9 Answers 9

81

That should absolutely match hidden files. The / at the end of the source says "every file under this directory". Nevertheless, testing and research bear you out. This is stupid behavior.

The "answer" is to append a dot to the end of the source:

scp -rp src/. user@server:dest/

The real answer is to use rsync.

5
  • Nice trick I did not realized this yet.
    – cstamas
    Jun 7, 2009 at 19:06
  • 25
    rsync -avz -e ssh --progress src/ user@server:dest/
    – MikeyB
    Jun 7, 2009 at 23:23
  • 2
    I can't reproduce that behavior. scp -r source/ host:source2 copies dot files. Works in OpenSSH 5.1 from 2007.
    – Mikel
    Mar 8, 2011 at 20:33
  • 14
    Note that adding a . at the end no longer works (2019) due to security issues. This is explained here: superuser.com/questions/1403473/scp-error-unexpected-filename
    – Stéphane
    Feb 12, 2019 at 21:44
  • 1
    scp: error: unexpected filename: .
    – QkiZ
    Jan 25 at 18:21
31

You can try rsync. It's better suited for this job:

rsync -av src/ user@server:dest/

(And its manual page is worth reading.)

3
  • 2
    I always use the --progress option for rsync, I can't live without it =D
    – Hofa
    Jun 7, 2009 at 21:21
  • 1
    @Hofa I usually use -P because it is shorter, already includes --progress and also includes --partial which can make sense if I am already interested in its progress ;-)
    – cstamas
    Mar 31, 2012 at 10:27
  • 1
    Use this if you need different port : rsync -av -e "ssh -p 2222" src/ user@server:dest/
    – Brain90
    Feb 5, 2020 at 12:57
9

Don't put a slash after the source directory. Your code would look like this:

scp -rp src user@server:dest/

This will create a directory 'src' under 'dest' on the remote machine, with all the hidden files included. It's probably not exactly what you want, but it will copy hidden files in src.

2
  • This will copy src to user@server:dest/, not contents of this directory.
    – QkiZ
    Jan 25 at 18:23
  • Totally agree and I think my answer said that. It will make a copy of src (and all its content) underneath dest/ on the destination server. It will not put a copy of all the things inside src directly under dest.
    – kbyrd
    Jan 26 at 19:17
5

To copy only hidden files, Use this command

scp -rp /path_to_copy_hidden/.[!.]* user@host:/path_to_paste/

Actual game is the /.[!.]* tag that is referring to files starting with .(hidden)

1
  • this should be accepted answer
    – QkiZ
    Jan 25 at 18:25
3

The following will solve the problem, this has been fully tested on our continuous integration environment

scp -rp src/. user@server:dest/
example scp -rp /usr/src/code/. [email protected]:/usr/dest/code/

Hope it helps

2
  • 4
    After updating scp recently, this now results in scp: error: unexpected filename: . . Make sure to test whether it works with your distribution, fellow Googler :) Feb 11, 2019 at 11:39
  • The command as they posted it did work in the past. A patch for vulnerability CVE-2018-20685, which you can view the contents of here, has left this functionality broken for the past few years. That being said, it's rather rude to imply someone didn't do their research at the time of posting an answer, especially an upvoted one. Things change over the course of years. No reason to be disrespectful about it.
    – Jyosua
    Jan 15 at 9:25
1

As scp supports regular expressions, this will nicely do the trick for you:

scp -rp src/(*|.*) user@server:dest/

0

None of the above scp solutions worked for me. However, I did find that the following worked on cygwin: scp -r directory/* host:directory The '*' matched all visible files and skipped the invisible.

0

If password login is disabled on the remote machine, and the only way to login is via public key, then you can use this:

$ rsync -av -s 'ssh -i /path/to/your/private/SSH/key' --progress [email protected]:/remote/source/directory/ /local/destination/directory/

It copies hidden files too.

Also please note that "user1" must have the permissions to read those files, for example you can't copy other user's ssh folders with this method.

-1

Distributed revision control handles hidden files

Because of the CVE-2018-20685 vulnerability, the /. trick can no longer be used with scp. However, distributed revision control like git or Hg Mecurial will handle hidden files like any other files. Here are the commands for my favourite Hg Mercurial:

server:$ sudo apt install mercurial
client:$ sudo apt install mercurial
client:$ hg init src
client:$ cd src/
client:$ hg addr
client:$ hg com -m "first commit"
client:$ cd
client:$ hg clone src ssh://user@server/dest/

Subsequent changes will need to be committed again with client:$ hg com -m "commit message" and then pushed using the client:$ hg push command. Learn more about pushing changes from this Hg Mercurial cheat sheet.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .