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

pushandpop
  • 1,386
  • 2
  • 10
  • 11

3 Answers3

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)

Hauke Laging
  • 90,279
  • 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 '15 at 15:05
  • @pushandpop A/* does make sense but there are situations in which it doesn't work. – Hauke Laging Jan 25 '15 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. – Stéphane Chazelas Jan 25 '15 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 ....) – Stéphane Chazelas Jan 25 '15 at 16:42
  • @StéphaneChazelas I guess there is a typo somewhere. find .../. causes an error here. – Hauke Laging Jan 25 '15 at 16:47
  • ... was an ellipsis for /home/username/A. It shouldn't give you a syntax error though, just a file not found one (unless you have a directory called ...). – Stéphane Chazelas Jan 25 '15 at 16:49
  • is adding . after / mandatory ? seems to work without it – Veverke Nov 10 '20 at 09:36
  • @Veverke It does work if you run the command only once (and know for sure that B doesn't exist). But run both commands twice and compare the results. – Hauke Laging Nov 10 '20 at 13:35
  • Use cp -a /home/username/A/. /usr/lib/B/ (i.e., instead of -r use -a) to preserve symlinks and file attributes. – Abdull Jan 10 '24 at 21:07
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.

michas
  • 21,510
  • 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 01 '18 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 07 '22 at 08:13
3

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

sudo cp -r /home/username/A/* /usr/lib/B/
terdon
  • 242,166
  • Thanks! But it says: /usr/lib/B/ is not a directory – pushandpop Jan 25 '15 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 '15 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 '15 at 14:55
  • is adding * after the / is mandatory ? seems to work without it – Veverke Nov 10 '20 at 09:35
  • 1
    @Veverke without it, you copy the directory. With it, you copy only what is inside the directory. – terdon Nov 10 '20 at 10:43
  • @that's why I asked, I always thought the same - my script had /*, but using only / seems to copy the files inside it (and adding it to a cp will create the dir as well). I am a beginner in linux but this is what I see when looking at the results running the command with both syntaxes. – Veverke Nov 10 '20 at 12:58
  • 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 '20 at 13:25