14

I have ubuntu file system directories in the root directory and I accidentally copied hundreds of files into root directory.

I intuitively tried to remove copied files by excluding file system like

rm -rf !{bin,sbin,usr,opt,lib,var,etc,srv,libx32,lib64,run,boot,proc,sys,dev} ./.

bu it doesn't work. What's the proper way to exclude some directories while deleting the whole?

EDIT: Never try any of the commands here without knowing what to do!

  • 1
    What shell are you using? Filename globbing is shell dependent when it comes to doing fancy stuff like that. – Kusalananda Jan 6 '17 at 21:02
  • 2
    Not an answer, but I would use for example mc. Select everything with *, then deselect specific files with - or Insert key. – pbm Jan 6 '17 at 21:05
  • 1
    Can you explain what 'mc' is? – MikeP Jan 6 '17 at 21:12
  • @Kusalananda it's /bin/bash – kenn Jan 6 '17 at 21:15
  • 3
    @MikeP: mc is Midnight Commander, a very useful imitation of Norton Commander. It runs in a terminal. (Both Midnight Commander and Norton Commander are examples of what is called an orthodox file manager.) – AlexP Jan 6 '17 at 21:18
19

Since you are using bash:

shopt -s extglob
echo rm -rf ./!(bin|sbin|usr|...)

I recommend to add echo at the beginning of the command line when you are running something what potentially can blow up the entire system. Remove it if you are happy with the result.

Note: The above command won't remove hidden files (those which name start by a dot). If you want to remove them as well then activate also dotglob option:

shopt -s dotglob
  • I used it to clean up the filesystem successfully. At first I tested it in a directory. I also tried rm -rf ./!(bin,sbin,..) comma seperated, but it removes all directories. – kenn Jan 7 '17 at 14:25
  • What is that !(...) syntax? From the example I intuitively thought ls ./!(*/) would list only files, but it doesn't work that way. – giusti Jan 7 '17 at 14:38
  • @giusti This syntax is extended pattern matching in filename expansion mechanism - you will find its description in the bash manual under Pathname Expansion chapter. It cannot be used to exclude files' types, only names, just like with star * or other globs. – jimmij Jan 7 '17 at 16:51
12

This command will show all non-directories in /:

find / -maxdepth 1 -type f

Once you have made absolutely sure no files are there that you wish to keep, you can use:

find / -maxdepth 1 -type f -delete

Safer, would be to move them elsewhere to ensure you aren't deleting something you want to preserve:

mkdir /root/preserve
find / -maxdepth 1 -type f -exec mv -- "{}" /root/preserve/\;

If, in addition to files, you also have directories that you've added to the root of the filesystem, this could be automated by excluding the LSB directories from an automated mv or rm, but honestly, since we're dealing with purging things in the root of the filesystem, I would strongly suggest you consider doing it manually if at all feasible.

If this is not feasible, something like this could do the trick:

#!/bin/bash
declare -a excludes
for item in root sys 'lost+found' mnt home proc etc opt boot lib lib64 libx32 sbin media srv dev var usr bin tmp run; do
    excludes+=("$item")
done
if ! [[ -d /root/preserve ]]; then
    mkdir -p /root/preserve
fi
IFS="\n"
for item in find / -type d -maxdepth 1; do
    really=true
    for exclude in ${excludes[@]}; do
        if [[ "$exclude" == "${item#/}" ]]; then
            really=false
        fi
    done
    if [[ "true" == "$really" ]]; then
        mv -- "$item" /root/preserve/
    fi
done

Once you've passed the scream test (i. e. your system still runs and you are not screaming in anguish), you can remove the contents of /root/preserve/.

Important note: Whatever you do, don't even think about running any permutation of rm -fr [ANYTHING GOES HERE] /.

  • your solution only deletes files but there are folders around too. – kenn Jan 6 '17 at 21:31
  • 1
    One too many times, I have heard shrieks of dismay from a poorly-aimed rm. Like a script with rm -fr $somepath/ with somepath uninitialized in it. I could have gone further in expressing how grave this is, but opted to remain family friendly in my admonition. – DopeGhoti Jan 6 '17 at 22:44
3

This should get the job done (though not in the same way as the OP asks):

ls -1 >1.txt
pico 1.txt 

remove all files/directories you want to keep

xargs rm < 1.txt

If your files all have the same name format, date, or something else, then there are other methods.

I'd look at the inodes - and see if they are sequential via ls -i |sort and if they are, then the new files will have larger inodes. Then using the same type of process as above...

ls -iF1 | sort |cut -c10- | grep -vE "\/|\@" >i.txt   #This part removes entries that are not regular files, such as directories and links.  
pico i.txt
xargs rm < i.txt

in the cut command above, check your inodes list first to make sure it is the right amount.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.