Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How do I delete directories but not the files inside them? I have tried the following:

rm -di /Users/arthur/Desktop/MyFolder 

remove /Users/arthur/Desktop/MyFolder? y
rm: /Users/arthur/Desktop/MyFolder: Directory not empty

I'm on a Mac. BTW, I want to do this automatically.

share|improve this question
    
Where should the files go? – slhck Apr 3 '12 at 7:23
    
@slhck up a directory – gadgetmo Apr 3 '12 at 7:30
up vote 6 down vote accepted

Method 1 – First moving, then deleting

Just move the files up one directory and then delete it. This will keep the contained file/folder hierarchy.

mv ~/Desktop/MyFolder/* ~/Desktop/MyFolder/..
rmdir ~/Desktop/MyFolder

Method 2 – Automating in a Shell Function

You can put this into a shell function defined in your ~/.bash_profile:

function rmd () {
  if [ -d "$1" ]; then
    mv "$1"/* "$1"/..
    rmdir "$1"
  else
    echo "$1 is not a directory"
  fi
}

As said before, this will only delete the parent folder, keeping the children hierarchy intact.


Method 3 – Recursive deletion

If you want to recursively remove all folders and just keep files contained, use the following instead:

function rmdr () {
  if [ -d "$1" ]; then
    p="$1"/..
    find "$1" -type f -exec mv '{}' "$p" \;
    rm -rf "$1"
  else
    echo "$1 is not a directory"
  fi
}

Note that this overwrites files with duplicate names.


Method 4 – Recursive deletion with duplicate awareness

Finally, if you want to keep duplicate files, you can check if they already exist. In this case, we'll prepend them with a random number string. Of course, there could be way more sophisticated methods than that, but you can see where this is going.

function rmdr () {
  if [ -d "$1" ]; then
    p="$1"/..
    # loop through all files
    while IFS= read -r -d '' file; do
      filename=$(basename "$file")
      # if it already exists, prefix with random number
      if [ -f "$p/$filename" ]; then
        mv "$file" "$p/$RANDOM-$filename"
      # if it doesn't exist, just move
      else
        mv "$file" "$p"
      fi
    done < <(find "$1" -type f -print0)
    # remove parent directory
    rm -rf "$1"
  else
    echo "$1 is not a directory"
  fi
}

Looping through find output is explained here.

share|improve this answer
    
Thanks. Is it possible to do this recursively? – gadgetmo Apr 3 '12 at 8:35
    
You mean, specify one directory, and then eliminate the complete directory hierarchy, just keeping the files? In that case, see my updated answer. – slhck Apr 3 '12 at 8:41
    
Thanks, accepted answer. But what if I have a directory like this: before If I run rmdr /Users/arthur/Desktop/MyFolder, it turns into this: after – gadgetmo Apr 3 '12 at 9:55
    
That's expected behavior since all files will be moved into the same target directory. In Unix, files with the same name will be overwritten by mv. The question is: What do you expect as output instead? Should duplicate files get another name? – slhck Apr 3 '12 at 10:08
    
They should get another name, if that is possible. Thanks. – gadgetmo Apr 3 '12 at 10:10

You must log in to answer this question.

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