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 fi
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/
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.
cd ..
ln trash/useful.file ./
rm -rf trash/*
mv useful.file trash/
Short answer
ls | grep -v "z.txt" | xargs rm
Details:
The thought process for the above command is :
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
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/
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:
-e
)glob
matching (default, like shown in the above example)-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.