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 di开发者_JS百科rectories 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 '{}' ';'
: callrm -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
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
P.S. I suggest -i
switch for rm
to prevent delition of important data.
P.P.S You can write the small script based on this solution and place it to the /usr/bin
(e.g. /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;
At least in zsh
rm -rf ^filename
could be an option, if you only want to preserve one single file.
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.
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:
- 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.
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/
you need to use regular expression for this. Write a regular expression which selects all other files except the one you need.
精彩评论