115

I'm trying to copy files and subfolders from A folder without the A itself. For instance, A folder contains next:

| file1.txt   
| file2.txt    
| subfolder1   

Executing next command gives me wrong result:

sudo cp -r /home/username/A/ /usr/lib/B/

The result is

/usr/lib/B/A/...copied files...

instead of..

/usr/lib/B/...copied files...

How can I reach the expected one without origin-folder

3 Answers 3

166

advanced cp

cp -r /home/username/A/. /usr/lib/B/

This is especially great because it works no matter whether the target directory already exists.

shell globbing

If there are not too many objects in the directory then you can use shell globbing:

mkdir -p /usr/lib/B/
shopt -s dotglob
cp -r /home/username/A/* /usr/lib/B/

rsync

rsync -a /home/username/A/ /usr/lib/B/

The / at the end of the source path is important; works no matter whether the target directory already exists.

find

mkdir -p /usr/lib/B/
find /home/username/A/ -mindepth 1 -maxdepth 1 -exec cp -r -t /usr/lib/B/ {} +

or if you don't need empty subdirectories:

find /home/username/A/ -mindepth 1 -type f -exec cp --parents -t /usr/lib/B/ {} +

(without mkdir)

9
  • 2
    The first one works just fine! Any ideas why home/username/A/* (with star-symbol) doesn't make sense? Variant with dot at the end helped me, thanks!
    – pushandpop
    Jan 25, 2015 at 15:05
  • @pushandpop A/* does make sense but there are situations in which it doesn't work. Jan 25, 2015 at 16:01
  • 3
    shopt is bash specific. With zsh, use *(D). with ksh93, FIGNORE='@(.|..)'. cp -t is GNU specific. The find one will not work properly as it will copy both A/ and its content (including subdirs) several times. Jan 25, 2015 at 16:37
  • 1
    You also want -maxdepth 1 (-mindepth and -maxdepth being GNU extensions now also supported by a few others. Portably find .../. ! -name . -prune -exec ....) Jan 25, 2015 at 16:42
  • @StéphaneChazelas I guess there is a typo somewhere. find .../. causes an error here. Jan 25, 2015 at 16:47
36

If on a GNU system, from man cp:

   -T, --no-target-directory
          treat DEST as a normal file

This allows you to write cp -rT /home/username/A/ /usr/lib/B/ to do exactly the right thing.

2
  • This should be the accepted answer, this is proper than shell globbing or using something else than cp. But that's true that -T won't work with a non-GNU cp.
    – noraj
    Nov 1, 2018 at 17:07
  • Nice, but this answer (nor the man page) doesn't explain why treating DEST as normal file results in this wanted behaviour.
    – Marki555
    Sep 7, 2022 at 8:13
3

Tell cp to copy the directory's contents and not the directory itself:

sudo cp -r /home/username/A/* /usr/lib/B/
7
  • Thanks! But it says: /usr/lib/B/ is not a directory
    – pushandpop
    Jan 25, 2015 at 14:52
  • 2
    You will need to shopt -s dotglob for this to work if there are any dotfiles in /home/username/A/.
    – talkloud
    Jan 25, 2015 at 14:52
  • 1
    @pushandpop well, yes. That's the target you had in your question so I assumed it was a directory. You need to create the target before attempting to copy files into it.
    – terdon
    Jan 25, 2015 at 14:55
  • 1
    @Veverke without it, you copy the directory. With it, you copy only what is inside the directory.
    – terdon
    Nov 10, 2020 at 10:43
  • 1
    @Veverke please post a new question if you need more details and show us the exact commands you used. That said, if you run cp -r foo/* bar one of two things will happen: if bar does not exist, or if it exists but is not a directory, you will get an error message. If it does exist and is a directory, then all non-hidden files/dirs from foo will be copied into bar. If you run cp -r foo/ bar, then if bar exists and is a directory, that will copy the directory foo and place it as a subdirectory of bar. If bar does not exist or is not a directory, you will get an error.
    – terdon
    Nov 10, 2020 at 13:25

You must log in to answer this question.

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