172

My goal is copy only all files from ~/local_dir to user@host.com /var/www/html/target_dir using scp and do not create local_dir category in local_dir.

/var/www/html/target_dir/files..

but not

/var/www/html/target_dir/local_dir/files.. when use -r parameter

2
  • 1
    Does scp * user@host.com:/var/www/html/target_dir not do what you want? If so, please edit with more detail of what you're trying to do & have tried so far. Sep 30, 2015 at 8:05
  • 1
    Appending /. is no longer work. More here Mar 20, 2019 at 9:13

5 Answers 5

223

scp has the -r argument. So, try using:

$ scp -r ~/local_dir user@host.com:/var/www/html/target_dir

The -r argument works just like the -r arg in cp, it will transfer your entire folder and all the files and subdirectories inside.

6
  • 19
    Your command created local_dir directory in /var/www/html/target_dir my goal is copy only files. Sep 30, 2015 at 8:25
  • 2
    Sorry, I got it wrong. Then just repeat the command, but like this: $ scp -r ~/local_dir user@host.com:/var/www/html/ Then rename new directory if needed.
    – parazyd
    Sep 30, 2015 at 8:31
  • 20
    Or $ scp -r ~/local_dir/* user@host.com:/var/www/html/target_dir Whatever floats your boat.
    – parazyd
    Sep 30, 2015 at 8:34
  • 32
    Change the wildcard * to a dot . and you'll copy the directory contents (including any dot files) without copying the directory itself. scp -pr ~/local_dir/. user@example.com:/path/to/target_dir
    – roaima
    Jul 21, 2017 at 22:25
  • 3
    Unfortunately, using . has been broken by a poorly implemented scp "bugfix" (see <superuser.com/questions/1403473/scp-error-unexpected-filename/…). rsync would be a working alternative.
    – rivy
    Jun 28, 2020 at 21:15
60

If your goal is to transfer all files from local_dir the * wildcard does the trick:

$ scp ~/local_dir/* user@host.com:/var/www/html/target_dir

The -r option means "recursively", so you must write it when you're trying to transfer an entire directory or several directories.

From man scp:

-r 
Recursively copy entire directories. Note that scp follows symbolic links encountered in the tree traversal.

So if you have sub-directories inside local_dir, the last example will only transfer files, but if you set the -r option, it will transfer files and directories.

3
  • 2
    1+ Because you need to read the comments in the accepted answer to get to the correct answer, while this one just explains it directly. Jul 5, 2017 at 10:01
  • Directories aren't copied: not a regular file.
    – Pathros
    Aug 9, 2021 at 13:10
  • 1
    i don't recomand using "*" because it won't copy hidden files and directories Jan 5 at 9:19
29

Appending /. to your source directory will transfer its contents instead of the directory itself. In contrast to the wildcard solution, this will include any hidden files too.

$ scp -r ~/local_dir/. user@host.com:/var/www/html/target_dir

Credit for this solution goes to roaima, but I thought it should be posted as an actual answer, not only a comment.

1
16

Follow these steps:

  1. Copy directory local_dir with all its sub-directories:

    scp -r ~/local_dir user@host.com:/var/www/html/target_dir
    
  2. copy only the contents of local_dir and not the directory local_dir itself:

    scp -r ~/local_dir/* user@host.com:/var/www/html/target_dir
    
  3. Do not use: scp -r ~/local_dir/. user@host.com:/var/www/html/target_dir as it throws an error(just tested and received the following error):

    scp: error: unexpected filename: .
    
4
  • 1
    I also get the error of unexpected filename . However, using the wildcard does not work either cause the directory has so many files that is exceeds the character limit for commands when the wildcard gets expanded. macOS Jan 8, 2020 at 10:17
  • @RichardKiefer : You can use wildcards like ? with * to further isolate the search results and then pass it to scp. Try this link, it may help: Wildcards Jan 14, 2020 at 6:15
  • Thanks Syed, but my point was that I actually want to target all elements in the folder, and not filter any. And if my directory has too many, than the wildcard will just not work. Jan 14, 2020 at 8:33
  • @RichardKiefer: My apologies Richard, to get all the files copied we can use a small bash script. Use: ls -l | awk '{print $9}' and redirect all the output (which would be all the file names) to a txt file. Read the txt file, one line at a time and use that input with scp to copy the files: input=/home/user/filename.txt while IFS= read -r line Jan 14, 2020 at 9:59
0

Also

rsync -avP ~/local_dir/ user@host.com:/var/www/html/target_dir/

should work.

And you can run it with -n at its end

rsync -avP ~/local_dir/ user@host.com:/var/www/html/target_dir -n

so that it simulates the operation and you can check that the result is what you wish for.

1
  • 1
    You would need to add a trailing / to ~/local_dir (i.e. rsync -avP ~/local_dir/ etc.) to prevent the creation of /var/www/html/target_dir/local_dir on the destination side, which is one key requirement of the OP.
    – AdminBee
    Jul 16, 2021 at 13:27

You must log in to answer this question.

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