Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Could someone explain why this happens?

Most specifically: Why is one 1's content copied to f? And why is f copied to g?

$ tree  
.

0 directories, 0 files

$ mkdir 1
$ mkdir 2
$ touch 1/a
$ touch 1/b
$ mkdir 1/c
$ touch 1/c/x
$ tree
.
├── 1
│   ├── a
│   ├── b
│   └── c
│       └── x
└── 2

3 directories, 3 files

$ cp -r 1/* 2/*
zsh: no matches found: 2/*

$ cp -r 1/* 2/*
$ mkdir 2/f
$ mkdir 2/g
$ cp -r 1/* 2/*
$ tree
.
├── 1
│   ├── a
│   ├── b
│   └── c
│       └── x
└── 2
    ├── f
    └── g
        ├── a
        ├── b
        ├── c
        │   └── x
        └── f

7 directories, 6 files
share|improve this question
    
I think you have an extra cp -r 1/* 2/* in there - it's done twice in a row with (apparently) different results. It should always complain about not finding a 2/* because the shell can't expand that glob - nothing matches it. And the contents of 1 is not copied to f in this example. –  Shawn J. Goff Jan 21 '12 at 23:49
2  
If the destination of the cp is kind of ambiguous, you can try --target-directory, e.g. cp --target-directory=2 fileglob1 fileglob2 I find that option very useful in scripts where I am not sure what globs will work and which ones won't; it helps prevent accidentally overwriting stuff. (Some versions of cp allow -t .) –  Aaron D. Marasco Jan 22 '12 at 1:00
add comment

1 Answer 1

up vote 8 down vote accepted

For cp, the destination is the last argument on the command line. You have specified 2/g as the last argument.

Before cp is executed, the command parameters are expanded. 1/* expands to 1/a 1/b 1/c. 2/* expands to 2/f 2/g. The final executed command is cp -r 1/a 1/b 1/c 2/f 2/g, which will copy all the arguments (except the last one) to 2/g.

If you are intending to copy things to 2, the second glob isn't necessary, making the command cp -r 1/* 2/. If you are intending to copy things to multiple destinations, you can't specify that with just cp; you can use a small loop, like the following:

#!/bin/sh
for path in ./2/*/; do
  cp -r 1/* "$path"
done
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.