简体   繁体   中英

Using find - Deleting all files/directories (in Linux ) except any one

If we want to delete all files and directories we use, rm -rf * .

But what if i want all files and directories be deleted at a shot, except one particular file?

Is there any command for that? rm -rf * gives the ease of deletion at one shot, but deletes even my favourite file/directory.

Thanks in advance

find can be a very good friend:

$ ls
a/  b/  c/
$ find * -maxdepth 0 -name 'b' -prune -o -exec rm -rf '{}' ';'
$ ls
b/
$ 

Explanation:

  • find * -maxdepth 0 : select everything selected by * without descending into any directories

  • -name 'b' -prune : do not bother ( -prune ) with anything that matches the condition -name 'b'

  • -o -exec rm -rf '{}' ';' : call rm -rf for everything else

By the way, another, possibly simpler, way would be to move or rename your favourite directory so that it is not in the way:

$ ls
a/  b/  c/
$ mv b .b
$ ls
a/  c/
$ rm -rf *
$ mv .b b
$ ls
b/

Short answer

ls | grep -v "z.txt" | xargs rm

Details :

The thought process for the above command is :

  • List all files (ls)
  • Ignore one file named "z.txt" (grep -v "z.txt")
  • Delete the listed files other than z.txt (xargs rm)

Example

Create 5 files as shown below:

echo "a.txt b.txt c.txt d.txt z.txt" | xargs touch

List all files except z.txt

ls|grep -v "z.txt"

a.txt
b.txt
c.txt
d.txt

We can now delete(rm) the listed files by using the xargs utility :

ls|grep -v "z.txt"|xargs rm

At least in zsh

rm -rf ^filename

could be an option, if you only want to preserve one single file.

You can type it right in the command-line or use this keystroke in the script

files=`ls -l | grep -v "my_favorite_dir"`; for file in $files; do rm -rvf $file; done

PS I suggest -i switch for rm to prevent delition of important data.

PPS You can write the small script based on this solution and place it to the /usr/bin (eg /usr/bin/rmf ). Now you can use it as and ordinary app:

rmf my_favorite_dir

The script looks like (just a sketch):

#!/bin/sh

if [[ -z $1 ]]; then
    files=`ls -l`
else
    files=`ls -l | grep -v $1`
fi;

for file in $files; do
    rm -rvi $file
done;

In bash you have the !() glob operator, which inverts the matched pattern. So to delete everything except the file my_file_name.txt , try this:

shopt -s extglob
rm -f !(my_file_name.txt)

See this article for more details: http://karper.wordpress.com/2010/11/17/deleting-all-files-in-a-directory-with-exceptions/

If it's just one file, one simple way is to move that file to /tmp or something, rm -Rf the directory and then move it back. You could alias this as a simple command.

The other option is to do a find and then grep out what you don't want (using -v or directly using one of find s predicates) and then rm ing the remaining files.

For a single file, I'd do the former. For anything more, I'd write something custom similar to what thkala said.

I see a lot of longwinded means here, that work, but with a/ b/ c/ d/ e/

 rm -rf *.* !(b*) 

this removes everything except directory b/ and its contents (assuming your file is in b/. Then just cd b/ and

rm -rf *.* !(filename) 

to remove everything else, but the file (named "filename") that you want to keep.

mv subdir/preciousfile  ./
rm -rf subdir
mkdir subdir
mv preciousfile subdir/

This looks tedious, but it is rather safe

  • avoids complex logic
  • never use rm -rf * , its results depend on your current directory (which could be / ;-)
  • never use a globbing * : its expansion is limited by ARGV_MAX.
  • allows you to check the error after each command, and maybe avoid the disaster caused by the next command.
  • avoids nasty problems caused by space or NL in the filenames.
cd ..
ln trash/useful.file ./
rm -rf trash/*
mv useful.file trash/

I don't know of such a program, but I have wanted it in the past for some times. The basic syntax would be:

IFS='
' for f in $(except "*.c" "*.h" -- *); do
  printf '%s\n' "$f"
done

The program I have in mind has three modes:

  • exact matching (with the option -e )
  • glob matching (default, like shown in the above example)
  • regex matching (with the option -r )

It takes the patterns to be excluded from the command line, followed by the separator -- , followed by the file names. Alternatively, the file names might be read from stdin (if the option -s is given), each on a line.

Such a program should not be hard to write, in either C or the Shell Command Language. And it makes a good excercise for learning the Unix basics. When you do it as a shell program, you have to watch for filenames containing whitespace and other special characters, of course.

you need to use regular expression for this. Write a regular expression which selects all other files except the one you need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM