Remove all but one ( or more ) kind of filetype
I’ve been trying to find a command to remove all files in a folder but not a kind of filetype. But I seems to not have any luck. What I’ve tried so far :
set extended_glob rm !(*.dmg) # this returns zsh:number expected rm ./^*.dmg # this returns no matches found
The version of zsh I’m using is
zsh 5.0.2 (x86_64-apple-darwin13.0.1)
.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
The extended_glob
option gives you zsh’s own extended glob syntax.
setopt extended_glob rm -- ^*.dmg rm -- ^*.(dmg|txt)
This removes files without an extension (e.g.
README
). If you want to keep those files, you can use the ~
operator to limit the matches:setopt extended_glob rm -- *.*~*.dmg
If you want to delete files in subdirectories as well, you can use
**
for recursive globbing. Pass the .
glob qualifier to restrict the matching to regular files, or use ^/
instead of .
to match all non-directories (including e.g. symbolic links). (Note that rm -r
wouldn’t help you since it would either delete a directory and all its contents, or not descend into a directory at all.)rm -- **/^*.(dmg|txt)(.)
You can set the
ksh_glob
option to get ksh globs. Beware that in the common case where the negative pattern is the last thing in the word, zsh may parse the parentheses as glob qualifiers (it doesn’t do this in ksh emulation mode).setopt ksh_glob rm -- !(*.dmg|*.txt) setopt no_bare_glob_qual rm -- !(*.dmg)
Method 2
You can use find
instead of your shell:
find . -mindepth 1 -maxdepth 1 ! -name "*.dmg" -delete
From
man find
:! expr True if expr is false. This character will also usually need protection from interpretation by the shell. -name pattern Base of file name (the path with the leading directories removed) matches shell pattern pattern. -delete Delete files; true if removal succeeded. If the removal failed, an error message is issued. If -delete fails, find's exit status will be nonzero (when it eventually exits). Use of -delete automatically turns on the -depth option.
If you can’t use
find
for whatever reason, here’s a way to do it with zsh
(or other shells). zsh
being zsh
, there is probably a simpler way of doing this but since I’m a bash
guy, this is what I came up with:for file in *; do if [[ ! "$file" == *.dmg ]]; then rm $file; fi; done
Method 3
Another way to remove files is with find
, xargs
and rm
:
find . -mindepth 1 -maxdepth 1 ! -name '*.dmg' -print0 | xargs -0 rm
Method 4
One can also use fd
(git-project) or fdfind
on debian systems, which has a very user-friendly interface.
The command is
fd --exclude='*.dmg' --hidden --exec rm fdfind --exclude='*.dmg' --hidden --exec rm # For Debian systems fd -E '*.dmg' -H -x rm # Short notation
Method 5
find path -mindepth 1 -maxdepth 1 -type f ! -name "*.dmg" -exec rm -vf {} ;
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