Remove all *.mp4 and *.zip but some files
Solution 1
The pattern !("file1" | "file2")
matches any file except file1␣
or ␣file2
where ␣
is a space. The way you quoted it is misleading: it's equivalent to !(file1 | file2)
or !("file1 "|" file2
)`.
There's no way in bash to combine a negative pattern with a positive pattern to say “all of these except for those”. In zsh, you can write
setopt extended_glob
rm /path/to/directory/*.(mp4|zip)~(keep*|1234.zip)
to remove this.mp4
and that.zip
but not keep-this.mp4
or 1234.zip
.
In bash, you can set the GLOBIGNORE
variable to exclude certain patterns from all matches.
shopt -s extglob
GLOBIGNORE='keep*:1234.zip'
rm /path/to/directory/*.(mp4|zip)
unset GLOBIGNORE
Alternatively, you can use find
, which lets you build arbitrarily complex boolean expressions.
find /path/to/directory \( -name '*.mp4' -o -name '*.zip' \) ! -name 'keep*' ! -name '1234.zip' -delete
Note that find
recurses into subdirectories. If this isn't desired, add -maxdepth 1
after /path/to/directory
.
If your find
doesn't understand -maxdepth
(it's common but not standard), use -type d -prune -o
instead. If your find
doesn't understand -delete
(same remark), use -exec rm {} +
instead.
Solution 2
There are several ways:
- Use find (portable as it does not need specific shell [bash])
find . -maxdepth 1 ! -name "exclude" -delete
or in case you have several patterns:
find . -maxdepth 1 ! \( -name "exclude" -o -name "exclude2" \) -exec rm -f {} \+
- Use GLOBIGNORE variable (bash only)
export GLOBIGNORE=exclude:exclude1:mask*
That will exclude mentioned files and masks from globing.
After that you can specify rm your_pattern
You can try it before with ls
Related videos on Youtube
![DrakaSAN](https://i.stack.imgur.com/cJOGz.png?s=256&g=1)
Comments
-
DrakaSAN almost 2 years
In one of my programs I call a
bash
command to remove all files in the directory, but some:bash -c shopt -s extglob shopt -s nullglob rm /path/to/directory/!("file1" | "file2")
Which for what I understand mean "Use bash on this command, use the extended pattern, remove all files but those"
It works good, but deletes every file but the ones put in the command.
What I would like is to remove all .mp4 and .zip in the directory but the ones I put in the command.
I think I'll have to add *.mp4 and *.zip somewhere in the command, but I have no idea where.
EDIT: For clarity, what I need is "Delete all .mp4 and .zip files, but keep thoses"
-
Anthon over 10 yearshave you tried
rm /path/to/directory/{*.zip,*.mp4}
? -
jirib over 10 yearsBashism... Bleah. Use find and learn how to make it portable between various system. Why would one need to use bash for such simple goal?
-
DrakaSAN over 10 yearsI am trying with
rm /path/to/directory/{*.zip, *.mp4, !("file1" | "file2")
-
DrakaSAN over 10 years@Anthon I get
rm: missing operand
-
DrakaSAN over 10 years@Jiri: Because the app is not meant to be portable. Is there other way to delete a file on raspbian?
-
jirib over 10 yearsIt's not about your app is not portable. It's about good behaviour. World is not only bash/Linux. Use the strength of bash when it makes really sense but this is not the case. Maybe one day you would sit in front of Solaris, *BSD, AIX... Then what? It's nothing more stupid than bash-based shebang when it is not needed.
-
DrakaSAN over 10 years@JiriXichtkniha: And at that moment I ll learn and use equivalent on whatever else system, I only use bash because my full app is in node.js, but I need a quick way to purge all unused files, and the fastest way I found is to use bash.
-
-
jirib over 10 yearsGNUism. Please be more general and use either 'exec rm' or 'xargs rm'. Thanks.
-
DrakaSAN over 10 yearsI m trying it right now, but it seems it will find all files but thoses I exclude, what I need is to find all .mp4 and .zip but thoses I want to exclude.
-
DrakaSAN over 10 yearsFor find, where is supposed to be the
)
? (several pattern) -
rush over 10 years@DrakaSAN you can use something like
find . -name *.ext ! -name 1.ext