82

When I try to use sftp to transfer a directory containing files, I get an error message:

skipping non-regular file directory_name

The directory contains a couple of files and two subdirectories.

What am I doing wrong?

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
haziz
  • 2,231
  • 4
  • 26
  • 37

11 Answers11

87

sftp, like cp and scp, requires that when you copy a folder (and its contents, obviously), you have to explicitly tell it you want to transfer the folder recursively with the -r option.

So, add -r to the command.

Kevin
  • 40,087
  • 16
  • 88
  • 112
  • 2
    -r after the put command? I am getting a "put: Invalid flag -r" error message message if I do. Adding it to the original sftp command also does not work. – haziz Dec 17 '11 at 09:12
  • 6
    Add `-r` to the `sftp` command when you're connecting. `sftp -r user@host` – Kevin Dec 17 '11 at 15:50
  • 1
    @Kevin I am getting the following error "sftp: unknown option --r" – Amatya Mar 27 '14 at 20:06
  • 1
    It looks like the `-r` option was added to OpenSSH `sftp` version 4.7. Go [here](http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man1/sftp.1?query=sftp&sec=1) and you can use the form at the top to see different versions of the man page. – Kenster Oct 02 '14 at 20:55
  • 4
    Beware that there is a [quite long standing bug](https://bugzilla.mindrot.org/show_bug.cgi?id=2150) in OpenSSH's SFTP: when copying recursively a directory to a remote server, the directory itself must already exist on the target server otherwise the transfer will fail with a non-explicit error message: `Couldn't canonicalise: No such file or directory`. – WhiteWinterWolf Dec 07 '15 at 10:09
  • 9
    should be something like: `# sftp user@remote-host` `#> get -r remote-folder` – hbinduni Aug 01 '17 at 05:03
  • `get -r foldername` does not work, `get: Invalid flag -r` – Abolfazl Mar 25 '19 at 04:59
  • It worked for me. – desmond13 Aug 11 '20 at 13:58
  • 1
    FYI - I am working on a server that has Centos 7 and have noticed that -r is not an option in sftp. Not every version has the same parameters. I have however found rsync to be handy for this purpose. The command scp does have -r available however. – Jeff Clayton Aug 13 '21 at 12:24
  • the -r flag worked for put for me: `put -r 'iTunes'` – John Tang Boyland Jul 01 '23 at 11:07
32

I can only suggest, you use rsync. It is somewhat of an industry standard, when moving files over secure connections.

rsync -alPvz ./source_dir server.com:destination_dir

It is what I've been using for years by now.

(the -a option takes care of things like directory recursion)

polemon
  • 11,133
  • 11
  • 69
  • 111
  • 7
    A bit of clarification on the parameters mentioned: `-a` = recursion + keep symbolic links, permissions, modification times, owner, group, special files and device files (the latter requires super-user privileges); `-l` = keep symbolic links (already included in `-a`); `-P` = show progress during the transfer + keep partially transferred files; `-v` = verbose mode (however it seems mandatory when using `-P` to avoid a weird (bug?) `protocol version mismatch` error); `-z` = enable compression of transferred data. – WhiteWinterWolf Dec 07 '15 at 13:52
  • @WhiteWinterWolf it seems to be version dependant whether the `-l` switch has to be used or not. I remember older versions didn't include `-l` in `-a`. – polemon Dec 07 '15 at 15:13
  • 3
    Using rsync is not adviced if you have very large number of files (40000+) as it might run out of memory - *especially* on smaller systems like Raspberry Pi 1-3. The more files you have, the more memory rsync uses (at least prior to version 3.1 - not sure if it's yet fixed in that or newer either), leading to rsync eventually using all system memory. – DocWeird Apr 16 '20 at 10:16
17

This works for me:

1) connect via sftp to remote host

2) change into the remote directory you wish to copy. (Example: cd Music)

3) change to the local directory you wish to copy stuff to. (Example: lcd Desktop)

4) Issue this command: get -r *

Anthon
  • 78,313
  • 42
  • 165
  • 222
Don Karon
  • 181
  • 1
  • 2
10

You may also be able to use use scp. The general format is

scp -rp sourceDirName username@server:destDirName

scp means "secure copy". The flags are

  • -r recurse into subdirectories
  • -p preserve modification times

I believe the rest of the items are self-explanatory

roaima
  • 107,089
  • 14
  • 139
  • 261
Bina Ramamurthy
  • 101
  • 1
  • 2
  • 1
    and scp -rp -P .... when using a non-standard port – Pancho May 07 '16 at 09:25
  • I'd also add the `-C` flag for compression (both scp/sftp). btw - scp uses sftp under the hood since OpenSSH 9 - see also https://www.openssh.com/txt/release-9.0 – Sandra Nov 10 '22 at 15:48
6

If you question is actually 'how do I use sftp to transfer a directory', then

 sftp -r user@server

But if you transferring a directory, I might suggest two better options, depending on your needs. sftp requires logging into the remote server in a ssh-like command prompt, but if all you want is the file(s), there are easier and quicker ways.

Scp

For a one time transfer, to upload try:

 # upload source directory to remote server
 scp -rp source_dir user@server:dest

 #download directory from remote server:
 scp -rp user@server:source_dir dest

 #specifying ssh key:
 scp -rp -i ~/.ssh/key user@server:source_dir dest

 #remote directory has spaces
 scp -rp -i ~/.ssh/key user@server:"source\\ dir" dest

Rsync

If you plan on syncing the directories on a regular basis, using rsync makes more sense. It performs deltas between the two directories, saving transfer time and data over the wire.

rsync -r -a -v -e ssh --delete source_dir user@server:dest

Here is a list of some of the most common rsync options: (taken from here)

  • --delete - delete files that don't exist on sender (system)
  • -v - verbose (-vv will provide more detailed information)
  • -e "ssh options" - specify the ssh as remote shell
  • -a - archive mode - it preserves permissions (owners, groups), times, symbolic links, and devices
  • -r - recurse into directories
  • -z - compress file data during transfer
  • --exclude 'foldername' – excludes the corresponding folder from transfer
  • -P – show progress during transfer

Hope that helps!

Dan Williams
  • 161
  • 1
  • 2
5

If rsync is not an option, I would next recommend lftp:

lftp sftp://[email protected]/path/path/

Then use the mirror command to recursively upload, like this:

mirror -R

(Note that recursion is the default. The -R is for reverse — to make the mirror command upload instead of download. Try adding --dry-run to do a trial to make sure it's doing what you expect.)

Or to upload without recursion:

mirror --no-recursion

You have to cd into the directories you want to mirror. Works great!

mattdm
  • 39,535
  • 18
  • 99
  • 133
Banago
  • 151
  • 1
  • 3
3

If you can, use sshfs. It's a FUSE filesystem, available on most modern unices, and works with any SFTP server. This is a remote filesystem: it allows you to manipulate remote files (over the SFTP protocol) with the usual utilities.

mkdir /mount/point
sshfs server.example.com:/remote/path /mount/point
ls /mount/point
cp -Rp /mount/point/somedir /local/location
fusemount -d /mount/point
Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
0

It's a bit of a kludge but what works for me is to:

  1. Use ssh to login to the remote machine
  2. Use sftp from the remote machine to your local machine
  3. Then use the get command with the -r option to move the directory and all of its files.
sam
  • 22,265
  • 4
  • 22
  • 30
0

you can get from the server to your local path by

scp -rp user@server:directoryname(full path) .
Bart
  • 2,151
  • 1
  • 10
  • 26
0

It's a workaround,

  1. You need to connect via SFTP.
  2. Go to the directory where files reside.(Example: cd [remote directory name])
  3. If you have many files with the same format, you can use the get *.[file format]. Example: If you have many files with .csv format, then use,
get *.csv 
0

I had the same need when I was already connected via sftp, and I didn't want to reconnect using -r param because in my case it's a bit annoying. There's a proxy which I have to connect first and then use a 2 factor token.

So, to avoid that, I did the following workaround: I compressed the folder using another ssh session and moved the resulting file on my sftp session.

SSH

tar -czvf myfolder.tar.gz myfolder

SFTP

put myfolder.tar.gz /server-path-name

Then, in the server (SSH), I extracted the folder by using:

tar -xzvf myfolder.tar.gz

If you're transferring a big amount of data, this workaround might be rather useful because it helps reducing the amount of data transferred and thus, the total transfer time.

  • I like your answer, as it makes it easier to see the total size, but does require space on the server to create the zip file. alternatively, you can use `-C` for compression with `sftp`, which would also reduce the amount transferred – Sandra Nov 10 '22 at 15:53