In a Linux terminal, how to delete all files from a folder except one or two?
For example.
I have 100 image files in a directory and one
From within the directory, list the files, filter out all not containing 'file-to-keep', and remove all files left on the list.
ls | grep -v 'file-to-keep' | xargs rm
To avoid issues with spaces in filenames (remember to never use spaces in filenames), use find
and -0
option.
find 'path' -maxdepth 1 -not -name 'file-to-keep' -print0 | xargs -0 rm
Or mixing both, use grep
option -z
to manage the -print0
names from find
In general, using an inverted pattern search with grep should do the job. As you didn't define any pattern, I'd just give you a general code example:
ls -1 | grep -v 'name_of_file_to_keep.txt' | xargs rm -f
The ls -1
lists one file per line, so that grep can search line by line. grep -v
is the inverted flag. So any pattern matched will NOT be deleted.
For multiple files, you may use egrep:
ls -1 | grep -E -v 'not_file1.txt|not_file2.txt' | xargs rm -f
Update after question was updated:
I assume you are willing to delete all files except files in the current folder that do not end with .txt
. So this should work too:
find . -maxdepth 1 -type f -not -name "*.txt" -exec rm -f {} \;
Use the not
modifier to remove file(s)
or pattern(s)
you don't want to delete, you can modify the 1
passed to -maxdepth
to specify how many sub directories deep you want to delete files from
find . -maxdepth 1 -not -name "*.txt" -exec rm -f {} \;
You can also do:
find -maxdepth 1 \! -name "*.txt" -exec rm -f {} \;
In bash, you can use:
$ shopt -s extglob # Enable extended pattern matching features
$ rm !(*.txt) # Delete all files except .txt files
find supports a -delete
option so you do not need to -exec
. You can also pass multiple sets of -not -name somefile -not -name otherfile
user@host$ ls
1.txt 2.txt 3.txt 4.txt 5.txt 6.txt 7.txt 8.txt josh.pdf keepme
user@host$ find . -maxdepth 1 -type f -not -name keepme -not -name 8.txt -delete
user@host$ ls
8.txt keepme