Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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

1 Answer 1

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

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.