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.

Why do tools like cp and rm treat directories separately from regular files? They both require the user to explicitly specify she wants a recursive behavior, or else they won't deal with directories at all.

My first interaction (a while back) with computers was on a Windows/GUI/point-and-click/drag-and-drop environment, it always seemed natural that these operations would behave the same, regardless of the target.

This behavior particularly frustrates me when I give commands with wildcards. What if I want to remove everything in a directory (*) except for non-empty subdirs?

I can only imagine that this is some sort of security feature to prevent the user from shooting herself in the foot, but this contradicts my understanding of a few Unix principles:

  • Unix doesn't usually protect the user from herself. It has always assumed the user knows what she's doing.
  • For Unix everything is a file. Isn't a directory just another file? Why are they treated differently?

My questions:

  • Is this behavior stemming from a technical limitation or is it a deliberate choice?

And in case of the latter,

  • are there any historical accounts of the reasons which motivated this choice?
share|improve this question
    
For rm at least, if you want it to ignore the difference between files and directories, you can put in your ~/.bashrc file: alias rm='rm -r'. –  BenjiWiebe Mar 1 '13 at 20:05
1  
See also the different but related question unix.stackexchange.com/questions/46066/… –  derobert Mar 1 '13 at 20:25
1  
You can't compare cp and rm with the windows file manager. Start cmd.exe and try copy and del and compare the behaviour. –  ott-- Mar 1 '13 at 20:46
add comment

2 Answers 2

up vote 9 down vote accepted

Derobert's Why unix mv program doesn't need -R (recursive) option for directories but cp does need it? basically answers your question: copying or removing a regular file is different from doing the same operation with a directory, because for a directory you have to process all the files contained therein. Hence the operation is fundamentally different.

Also worth noting is that there is a special utility rmdir which can only act on empty directories. Without checking the facts this leads one to conclude that maybe originally rm was only able to remove non-directories and deep remove had to be achieved by recursively using rm to empty directories and then rmdir to remove those.

share|improve this answer
    
rmdir is also the name of the system call that used to delete a directory. The directory must be empty for the system call, and utility of the same name is just "front-end", similar to the unlink command and utility. –  jordanm Mar 1 '13 at 22:05
    
Exactly - that's what leads me to believe that originally rm might have been unable to remove directories at all (because the command line utilities are often just relatively simple wrappers around syscalls). –  peterph Mar 2 '13 at 20:28
    
The title of my question might mislead to think I'm asking about the technical details. I was asking if it's a deliberate choice. I wonder if I'm the only one to think that from an end-user point of view this behavior is inconsistent. I'm accepting your answer because it's indirectly answers my question: technical limitations in Unix internals (at a syscall level) seem to be the origin of this behavior, and legacy probably prevents us from doing it any other way today. Aren't "simple wrappers around syscalls" supposed to give us more intelligent behaviors? –  rahmu Mar 5 '13 at 0:33
1  
From the end-user POV, it seems strange indeed, but you actually were asking about the reasons. :) As for the wrappers - it all depends on how "simple" they are (and what you still want to call "simple"). Modern rm definitely is not just a simple wrapper (it is able to remove mroe files at once and directories as well). If you don't like giving it the the -r option, use aliasing functionality of your shell or create your own wrapper that will put it in place (which would be slower, but independent of the shell you are using). –  peterph Mar 5 '13 at 11:11
add comment

In some UNIX flavors, the man page of rm specifies it as a command to unlink a file.
In UNIX, files are objects in the filesystem called Inodes, with no names or location apart from an ID in the filesystem. Their names are references to them in various directories, which are a type of file that is indexing the files (or directories, since they are files) that are listed in it.
When un-linking a file, the reference count of the file decreases, and when it reaches 0, it is in fact deleted, since it is marked as free by the filesystem and it's blocks/extents are marked free as well.

If you had the ability to rm a directory without unlinking the files within it first, you will reach a point where you have inodes referenced in your filesystem but cannot be accessed by any normal means.
Since there is a reference to them according their reference count, they are not marked as deleted and become lost files.
This gets even more complex when the lost "files" are directories, and as such increases the potential amount of lost storage in the filesystem.

So rm -r was added, as a feature to ease the life of UNIX users, in expense of standard "UNIX spirit", as it is more complex than the classic UNIX utilities as it is descending to directories and removing files within,

In addition, in the early time of UNIX, systems did not have a lot of memory, and mapping the recursive structure of a directory did have a performance penalty, and sometimes it was impossible to do without splitting the work.

cp, reads a file and copies it, block by block. If it were to copy a directory the same as it does a file, it would add references to the files within without increasing their reference count, which could lead to inconsistent data (if reading/writing to an inode who's blocks marked as free since their original inode was deleted), lost data - since deleting the last (known) reference to a file could cause it's inode number to be recycled.

For the tl;dr crowd:
Directories in UNIX are a type of file, that's true, but since the information within them is treated differently by the system, as it is metadata of the filesystem, the commands manipulating files cannot work on directories without a change in their behavior to manipulate the dependent metadata as well.

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.