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.

This is a kind of "wtf?" question, so I'm sorry if I will disturb someone's vision of how things should be or if I will just annoy you with the "stupid" question.

I always get messed up when need to use cp or mv: "do I need -R option when working with dir?" In GNU coreutils cp does need -R and mv doesn't. I didn't check *BSD, Solaris, HPUX because I don't have any.

I just can not find any reason why cp needs -R option for copying dirs and mv doesn't. I think that cping dirs without -R (but behaving recursively like there's -R and like mv does) wouldn't cause any problems except breaking someone's habits on using the tool.

Do you know any explanation? May be it had a reason long time ago?


Additional question: why don't coreutils developers make cp copy dirs recursively by default?

share|improve this question

3 Answers 3

A directory is (conceptually) a special "file" which contains a list of names, and the inode numbers those names point to. Some of names can be subdirectories. There is a special entry .. which points to the parent directory.

So, its clear, changing the name of a file is easy: you just change the name in the directory entry, nothing else. This holds whether the file is actually a file, or is a "file" used to store another directory's contents. Indeed, the same rename syscall does both.

Copying, however, is a much less trivial operation. You could just copy the directory "file", but then you'd have two directories where are the files are the same (they'd be hardlinks). If you had a system that allows hardlinks to directories, those would be to, but since no modern system allows that, at least to non-root, you have to do that copy for each subdirectory. You can actually ask cp for this behavior with cp -lR: -l for hard link, -R for that recursion.

But leaving everything linked is likely not what you want. Instead, you want cp to copy each file. That's a fairly expensive operation: each file must be read into memory, and written back out to disk in a second location. It actually takes several syscalls, to open, read, write, and close the files, and that has to be repeated for each file.

Traditional filesystems work this way on disk, too. There isn't any way to copy a bunch of files, other than to go through each one individually and copy it, and those are the types of filesystems that were in use when the basic command line utilities were designed.

share|improve this answer
    
is mving from one file system to another the same "just change the name in the directory entry"? –  khrf Aug 22 '12 at 13:02
3  
No, cross-filesystem is the same as a copy + delete (indeed, the rename syscall will fail for cross-filesystem). Not sure if, historically, mv even supported cross-fs moves. –  derobert Aug 22 '12 at 13:18
    
so you want to say that mv tool was created just for renaming files? and later it was modified to support cross-fs moves with copy+remove? then why don't coreutils developers make cp copy dirs recursively by default? isn't it a good UX improvement too? –  khrf Aug 22 '12 at 15:27
6  
I can tell you, from direct experience not speculation, that classical mv did not support cross-device moves. It used to just try a rename() and print an error message if it failed. I still remember the shocked feeling I had the first time I accidentally used the new feature. Why is this mv taking so long? Oh, it's doing a recursive copy that I didn't intend! –  Alan Curry Aug 22 '12 at 19:16
5  
@RuslanKhusnullin Command-line options to common commands are very hard to change, due to their use in shell scripts. Someone may be depending on the current refuse-to-copy-dirs behavior of cp. The cross-fs stuff was probably judged less likely to cause breakage, though as you can see, it still surprised Alan. –  derobert Aug 22 '12 at 20:12

Let me start by asking another question:

What is the difference between cp and cp -R?

Well, without the -R flag, it's only possible to copy files, because it's rather unusual that someone wants to non-recursively copy a directory: A non-recursive copy would just result in a second name for the directory, pointing to directly the same directory structure. Because that's rarely what people want, and there is actually a separate program that does this (ln), a non-recursive copy of directories is not allowed.

What then could be the difference between mv and mv -R?

mv a b just renames a single entry in the directory, so if a directory is mved, its contents are automatically also moved. In that sense, mv already provides the recursive property, i.e. the "renaming" of all entries in the renamed directory, e.g. from a/1 to b/1. A mv that does not do that, i.e. which renames a directory a to b, but keeps a/1 as a/1, is not what people understand when they refer to moving something: When you move a cupboard, the contents of the cupboard are moved as well. That operation is also already available, it's called mkdir.

share|improve this answer
    
That's right, I just was thinking of cp and mv as operations that they are named: 'make a copy' and 'move'. So if I want to make a copy of a cup of coffee, I'd expect to have another cup of coffee with the same filling (coffee drink). The problem is that the tools are not intended for 'usual people' but for nerds who are aware of disk and file system structure, not virtual entities like files and dirs of files. –  khrf Aug 24 '12 at 8:11
    
Well structured, reasoned response. –  Spedge Aug 28 '12 at 18:34
1  
@RuslanKhusnullin Your coffee analogy works for cp and mv too - it does not require any level of "nerdness" to understand, just basic common sense. A true copy of a cup of coffee is not an empty cup - you have to recursively copy not only the cup, but all of its contents (the coffee) too. However, when you move a cup of coffee you don't have to move the contents separately - the contents move with the container naturally. –  jw013 Jan 18 '13 at 20:02
    
@jw013 You've impressed me with "when you move a cup of coffee you don't have to move the contents separately", it really makes sense, thank you. But it's another layer of abstraction. I think you mean "treat a file as an inode" while I think of files like of bytes sequences without meta-information. –  khrf Jan 23 '13 at 20:58

Usually when I'm messed up with Unix logic I look at Plan9 to see how Unix inventors' implemented the same tasks years later without stucking on backward compatibility.

So Plan9 offers cp and mv tools to operate with files only.

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

For copying a dir there's dircp that is really @{cd fromdir && tar c .} | @{cd todir && tar xT} (rc shell syntax)

For moving a dir I think there's only dircp d1 d2 && rm -r d1

I think this decision to limit cp and mv for file operations only (not dirs) brings more clearness to disk operations and using tar for copying file trees is very comfortable for understanding and scripting.

share|improve this answer

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.