2

The following works correctly (ie does what I want)

 cd /var/www/release/
 mkdir wiki
 cp -rp ../html/wiki ./

However if I do (what seems more intuitive)

 cp -r ../html/wiki ./wiki

it will create /var/www/release/wiki/wiki (what I never want)

This behaviour is the same with mv. I am hoping that someone will explain the logic behind this behaviour so I get it right first time in future

1
  • 3
    My interpretation is that, in cp -r ../html/wiki ./wiki, you're telling it to copy the directory itself into a directory named wiki. Since wiki exists, it copies it into there. You could alternatively use cp -r ../html/wiki/* ./wiki to tell it to copy the files into the directory. Commented Jul 25, 2014 at 14:33

3 Answers 3

1

If you want to copy an entire directory as SOURCE, cp wants a directory as DESTINATION, to know where it should be stored.

The mistake you did was not removing the directory /var/www/release/wiki after your mkdir and cp -rp ... test.

So cp -r ... did, what you told it to do: Copy ../html/wiki into the existing directory ./wiki and thus creating another sub-directory called wiki.

Just remove /var/www/release/wiki and then do the cp -r command again, and you'll see it works as intended.

3
  • that works as you say but now I'm more confused!
    – zzapper
    Commented Jul 25, 2014 at 14:45
  • @zzapper You did mkdir ./wiki and thus creating a wiki directory in release. Now you did tell cp to copy the directory ../html/wiki and it's contents to ./wiki. Another way to explain it: You have a source bin ../html/wiki. You placed a bigger destination bin ./wiki in release. Now you placed the bin ../html/wiki including it's contents (apples/fish) inside of the bigger bin. Instead, you should have not placed a bigger bin in release and just moved/copied the source bin to release.
    – polym
    Commented Jul 25, 2014 at 14:49
  • That's cleared up why there is differential behaviour I hadn't understood the concept of a bin
    – zzapper
    Commented Jul 25, 2014 at 14:55
1

There are 3 forms of cp and mv

cp/mv [OPTION]... [-T] SOURCE DEST
cp/mv [OPTION]... SOURCE... DIRECTORY
cp/mv [OPTION]... -t DIRECTORY SOURCE...

Form 1 and 2 are of form cp/mv a b, in form 2 b is a existing directory, but in form 1 b is a destination. To avoid this ambiguity do not use form 2. Use form 1 for what you are trying to do, with -T. Use form 3 to move or copy to an existing directory.

1

When the last argument to cp is an existing directory, cp copies the source file(s) into that directory. mv does the same.

You would like to merge the source directory with the target directory. But that would only make sense when the source is a directory. So when you run cp somefile existing-directory/, you end up with existing-directory/somefile; and when you run cp -r somedir existing-directory/ you end up with existing-directory/somedir. The behavior that you find intuitive (but which I don't) would require that cp makes a difference depending on whether the source is a directory or not, so cp -r somefile somedir existing-directory/ would create existing-directory/somefile but not existing-directory/somedir.

cp something existing-directory copies the source into the target directory. If the source is a directory and you want to copy its contents, run

cp -rp something/* existing-directory/

Note that this omits files whose name begins with a .. If you want to include them, an easy way is to use rsync instead:

rsync -a something/ existing-directory/

With rsync, if you put a / at the end of the source, then the source's content is copied into the destination directory. Without a trailing / on the source, the source is created as an entry in the destination directory.

You must log in to answer this question.

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