In Linux Terminal, How to Delete All Files in a Directory Except One or Two

In Linux terminal, how to delete all files in a directory except one or two

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

delete all directories except one

With bash you can do this with the extglob option of shopt.

shopt -s extglob
cd parent
rm -rf !(four)

With a posix shell I think you get to use a loop to do this

for dir in ./parent/*; do
[ "$dir" = "four" ] && continue
rm -rf "$dir"
done

or use an array to run rm only once (but it requires arrays or using "$@")

arr=()
for dir in ./parent/*; do
[ "$dir" = "four" ] && continue
arr+=("$dir")
done
rm -rf "${arr[@]}"

or

for dir in ./parent/*; do
[ "$dir" = "four" ] && continue
set -- "$@" "$dir"
done
rm -rf "$@"

or you get to use find

find ./parent -mindepth 1 -name four -prune -o -exec rm -rf {} \;

or (with find that has -exec + to save on some rm executions)

find ./parent -mindepth 1 -name four -prune -o -exec rm -rf {} +

Oh, or assuming the list of directories isn't too large and unwieldy I suppose you could always use

rm -rf parent/*<ctrl-x>*

then delete the parent/four entry from the command line and hit enter where <ctrl-x>* is readline's default binding for glob-expand-word.

Using find - Deleting all files/directories (in Linux ) except any one

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/

How to delete all files or Sub-folders (both) in a folder except 2 folders with shell script

You haven't specified which shell you're using, but if you're using bash then extended globs can help:

printf '%s\n' !(@(conf|foldername2)/)

If you're happy with the list of files and directories produced by that, then pass the same glob to rm -rf:

rm -rf !(@(conf|foldername2)/)

Inside a script, you may need to enable extglob using shopt -s extglob. Later, you can change -s to -u to unset the option.


If you're using a different shell, then you can add some more options to your find command:

find  -maxdepth 1 ! -name 'conf' -a ! -name 'foldername2' -exec rm -rf {} +

Try it without the -exec part first to print the matches rather than deleting everything.

How to delete all files except directories?

find . -maxdepth 1 -type f -print0 | xargs -0 rm

The find command recursively searches a directory for files and folders that match the specified expressions.

  • -maxdepth 1 will only search the current level (when used with . or the top level when a directory is used instead), effectively turning of the recursive search feature
  • -type f specifies only files, and all files

@chepner recommended an improvement on the above to simply use

find . -maxdepth 1 -type f -delete

Not sure why I didn't think of it in the first place but anyway.

Delete all files and directories but certain ones using Bash

You may try:

rm -rf !(mysql|init)

Which is POSIX defined:

 Glob patterns can also contain pattern lists. A pattern list is a sequence
of one or more patterns separated by either | or &. ... The following list
describes valid sub-patterns.

...
!(pattern-list):
Matches any string that does not match the specified pattern-list.
...

Note: Please, take time to test it first! Either create some test folder, or simply echo the parameter substitution, as duly noted by @mnagel:

echo !(mysql|init)

Adding useful information: if the matching is not active, you may to enable/disable it by using:

shopt extglob                   # shows extglob status
shopt -s extglob # enables extglob
shopt -u extglob # disables extglob

Delete all files except the newest 3 in bash script

This will list all files except the newest three:

ls -t | tail -n +4

This will delete those files:

ls -t | tail -n +4 | xargs rm --

This will also list dotfiles:

ls -At | tail -n +4

and delete with dotfiles:

ls -At | tail -n +4 | xargs rm --

But beware: parsing ls can be dangerous when the filenames contain funny characters like newlines or spaces. If you are certain that your filenames do not contain funny characters then parsing ls is quite safe, even more so if it is a one time only script.

If you are developing a script for repeated use then you should most certainly not parse the output of ls and use the methods described here: http://mywiki.wooledge.org/ParsingLs

How to delete all files except the N newest files?

You can use this command,

ssh -t xxx.xxx.xxx.xxx "cd /directory_wanted; ls -t *.tgz  | tail -n
+11 | xargs rm -f; bash"

In side quotes, we can add what ever the operations to be performed in remote machine. But every command should be terminated with semicolon (;)

Note: Included the same command suggested by silentMonk. It is simple and it is working. But verify it once before performing the operation.



Related Topics



Leave a reply



Submit