I have a lot of files and folders in a specific folder and I want to delete all of them; however, I wanted to keep files X, Y, and Z.
Is there a way I can do something like: rm * | but NOT grep | X or Y or Z
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Instead of using rm, it may be easier to use find. A command like this would delete everything except a file named exactly ‘file’
find . ! -name 'file' -delete
Many versions of should be able to support globbing and regular expression matching.
You could also pipe the output of find to rm as well
find . ! -name '*pattern*' -print0 | xargs --null rm
Method 2
Using zsh, with setopt EXTENDED_GLOB, using the ~ operator (except)
rm -- *~(x|y|z)
or ^ operator (negation):
rm -- ^(x|y|z)
But, you should probably instead move the files elsewhere, then delete everything. It’s far safer in terms of finger slips, such as hitting enter too soon.
Method 3
ls -1 | grep -v "^[XYZ]$" # | xargs rm -r
Attention: Run the command and if the files to be deleted are the right ones, run it again and delete the hash character “#”.
If the filenames are more complicated then that, do
ls -1 | egrep -v "^file1$|^filename2$|^f1le$" # | xargs rm -r
Again, first look at the results then remove the hash sign.
This version – as suggested in the comments – saves some characters and looks a bit clearer.
ls -1 | egrep -v "^(file1|filename2|f1le)$" # | xargs rm -r
Method 4
Later versions of bash have the extglob shell option that gives you a syntax for doing what you want (check your man page under “Pathname Expansion” to see if your installed version has it):
$ shopt -s extglob # turn on extended globbing $ rm !(X|Y|Z)
To test, I suggest you first replace rm with echo to see if the list of files to be deleted is what you expect.
Method 5
Move the files you want to keep away. Go up one level, delete the folder. Re-create the folder and move those files back.
Method 6
It will delete all (including hidden) except selected files/folders in the CURRENT directory.
find . -maxdepth 1 ! -name "file1.php" ! -name "file2.js" ! -name "dir1" ! -name "dir2" ! -name . -exec rm -r {} ;
Method 7
This is what I set up as a .sh script for an OSX/MacOS logout hook, works well enough.
#! /bin/bash
for dir in /PathToFolder/*
do
if [ ! "$dir" = "/PathToFolder/FolderToKeep1" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep2" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep3" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep4" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep5" ] && [ ! "$dir" = "/PathToFolder/FolderToKeep6" ] ; then
echo ${dir}
sudo rm -R $dir user
dscl . -delete $dir
fi
done
exit 0
Method 8
With GNU-find you can use the -delete switch, which removes directories, if empty, too:
find tmp -not -name X -not -name Y -not -name Z -delete
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0