How to delete all files in a directory except some?
Solution 1
What I do in those cases is to type
rm *
Then I press Ctrl+X,* to expand *
into all visible file names.
Then I can just remove the two files I like to keep from the list and finally execute the command line.
Solution 2
To rm
all but u,p
in bash just type:
rm !(u|p)
This requires the following option to be set:
shopt -s extglob
See more: glob - Greg's Wiki
Solution 3
You can use find
find . ! -name u ! -name p -maxdepth 1 -type f -delete
-
!
negates the next expression -
-name
specifies a filename -
-maxdepth 1
will make find process the specified directory only (find
by default traverses directories) -
-type f
will process only files (and not for example directories) -
-delete
will delete the files
You can then tune the conditions looking at the man page of find
Update
- Keep in mind that the order of the elements of the expressions is significant (see the documentation)
-
Test your command first by using
-print
instead of-delete
find . ! -name u ! -name p -maxdepth 1 -type f -print
Solution 4
Simple:
mv
the files you want in a upper directory, rm
the directory and then mv
them back.
Solution 5
Somewhat similar to this answer but no special options are needed, as far as I know the following is "ancient" functionality supported by any (vaguely) /bin/sh resembling shell (e.g. bash, zsh, ksh, etc)
rm [^up]
Ashot
Updated on September 18, 2022Comments
-
Ashot over 1 year
I need to delete all files in a directory, but exclude some of them. For example, in a directory with the files
a b c ... z
, I need to delete all except foru
andp
. Is there an easy way to do this?-
Joe over 11 yearsThe answers below are a lot better, but you could just make the files to save read-only, delete all, and then change them back to their original permissions (as long as you don't use rm -f). You'd have to know what permissions to restore and you'd have to know that nothing needed write access to them during the process. This is why the other answers are better.
-
Admin over 11 yearsIf you also want to delete hidden files run
shopt -s dotglob
before runningrm (...)
.
-
-
slhck over 11 yearsYou need to
shopt -s extglob
, @Ashot. Also, it's just files, not directories, which is why I've removed the-rf
options in your command. -
glenn jackman over 11 yearsThis works for the 1-char filenames. For longer names, sparkie's answer is better.
-
user over 11 yearsWhat would be wrong with
rm [^up]*
? I do similar things rather often. -
Frerich Raabe over 11 yearsI guess this works only as long as the list of files which
*
expands too isn't getting too long. :-} -
Oliver Salzburg over 11 years@FrerichRaabe: Indeed. If it's too long a different approach will be required. Luckily we now have a list of great options :)
-
Michał Šrajer over 11 yearsorder of predicates is critical here. If one put
-delete
just after.
it will be disaster (will delete all files in CWD) -
kojiro over 11 yearsThis could be written more compactly as
find . -maxdepth 1 -type f -name '[^up]' -delete
-
user over 11 yearsThis does not work on my shell (GNU bash 4.1.5(1)). Be sure to test it first with something a little less harmful than
rm
or in a testing directory! -
Matteo over 11 years@kojiro yes but only for files that are just one letter. With more complex names the regex could be a mess.
-
reinierpost over 11 years@Konerak:
rm
without-r
won't remove subdirectories. -
John S over 11 years@MichaelKjörling - this would delete all files beginning with either u or p, not just those with the names u and p. I think the OP (@Ashot) meant the a-z and u,p,etc. symbolically and not literally.
-
hlascelles over 11 yearsIt reminded me the same thing. But temporarily moving out of folder may not be a good idea in the era of multitasking :)
-
Matteo over 11 yearsYou need to specify a directory before the expression (`find . -regextype ...).
-
Matteo over 11 years
-regextype
will only work on GNU versions -
Matteo over 11 yearsgrep will not handle extended regexpt by default: either use
-E
oregrep
-
Matteo over 11 yearsThis will overwrite files with the same name in the destination directory
-
sparkie over 11 yearsno - my find version (debian squeeze) does definitively not require an explicit directory before the expression if the current directory should be used
-
Matteo over 11 years@sparke: this just works on GNU implementations
-
rjmunro over 11 years@Matteo No it won't. The grep isn't grepping the files, it's grepping the output of the ls command. You're thinking of something like
grep -L (u|p)' * | xargs rm
where-L
means list filenames not containing a match. -
rjmunro over 11 yearsOh, you mean any file who's name contains
u
orp
, not any file containing au
or ap
. That is correct. You can fix by usingegrep -v '^(u|p)$'
-
anjaly over 11 yearsEsc followed by * will also expand the "*".
-
Terence Johnson over 11 years
find
is my best friend, especially when there are too many files to glob -
sam hocevar over 11 yearsI am downvoting this because while it can be handy, it also is non-atomic and effectively removes all files from the directory during a short period of time; this would not be acceptable if, for instance, the files are being shared on the network.
-
Santosh Kumar over 11 yearsThis only works with
rm
; was looking formv
,cp
,chmod
etc.. :( -
Oliver Salzburg over 11 years@SantoshKumar: That doesn't make sense to me. The expansion will always work, it doesn't depend on what command you want to use afterwards.
-
Santosh Kumar over 11 years@OliverSalzburg Sorry, the combination is little bit confusing. I think you should write like
Ctrl
+Shift
+x
+*
-
Oliver Salzburg over 11 years@SantoshKumar: But that's not the combination.
-
Nick over 9 yearsHere is remove everything except these matches!
ls | grep -v 'vuze\|progs' | xargs rm -rf
-
flungo about 9 yearsWorks in practice but can't be scripted. I think the find solution is the best.
-
mzuther almost 9 yearsIf you need to exclude one file of a selection of files, try this:
rm !(index).html
. This will delete all files ending in ".html" with the exception of "index.html". -
Mikko Rantalainen over 8 years@sparkie: not defining the directory (first parameter) for
find
is a GNU extension offind
command. The same applies for-regextype
option. In addition, your command will delete files in subdirectories, too, whereas the original question clearly asked about files in a directory. -
Forever Learner over 6 years@Oliver Salzburg, the combination is not working on my Korn shell , what I might be doing wrong could you please advise? solution from slowpoision , esc followed by * worked though. Thanks
-
Jan Heinrich Reimer about 4 yearsAlso you'd need write access on the parent directory, which you likely not have on a shared web server.
-
Mohan Munisifreddy about 4 years+1 for the explanation of all arguments
-
david over 2 years+1 as it works with
sh
vs rm fashion