Best Way to Copy Dotfiles

I've seen a lot of convoluted solutions floating around regarding how to copy files starting with .. The problem everyone is trying to avoid is that when you run something like:

cp -r A/.* B/

The above command starts copying everything the entire "A" directory (.) and then from the parent directory (..) on down. Sure you'll get everything in "A", dotfiles and otherwise, but you'll also get everything else at the same directory level as "A".

What you really want to do is more like this:

cp -r A/.??* B/

Now you'll grab most dotfiles, all directories starting with a dot but avoid the mess trying to work around recursively copying . and ..

Dotfiles you'll still miss are those that are named something like .a (a dot followed by a single non-dot character). Files like:

.a
.b
.c

If that's important to you you can improve on the above command with something like:

cp -r A/.*[!.]* B/

Now we'll catch files like .a. The trade off? Now we'll miss files that are named exclusively with dots:

$ touch A/... A/.... A/............
$ ls -A A/
...  ....  ............
$ cp -r A/.*[!.]* B/
cp: cannot stat ‘A/.*[!.]*’: No such file or director

You can fix that by adding something like:

cp -r A/.*[!.]* A/..[.]* B/

That said, if what you want is to copy all files and directories then try this:

cd A/
cp -r $(ls -A) ../B

By using ls -A you'll get a list of all files and directories without the special directory entries for . and ... It's not a perfect solution. You'll run into problems with filenames containing spaces, etc. You're better off using find -print0 at this point.