Reputation: 119
i have a bash script that should all files that are not .avi, .mp4 and .mkv.
This is what i tried:
#!/bin/bash
FILES=$(find /home/mattia/test/ -type f -name '*.*')
for f in $FILES
do
ext=${f#*.}
echo $ext
if [[ "$ext" != "mp4" || "$ext" != "mkv" || "$ext" != "avi" ]]; then
rm -f $f
echo deleted
fi
done
But this script deletes all files.
Upvotes: 2
Views: 87
Reputation: 4969
It is logical that
[[ "$ext" != "mp4" || "$ext" != "mkv" || "$ext" != "avi" ]]
is always true. For example: if the file name is movie.avi
, "$ext" != "mp4"
will be true and therefore the complete if will always be true.
As always, there are many ways to solve this. Janos did it in find
; an alternative would be:
find /find /home/mattia/test/ -type f -name '*.*'home/mattia/test/ -type f -name '*.*' |
egrep -v '.mp4$|.mkv$|.avi$' |
xargs rm
Or, in your loop:
#!/bin/bash
FILES=$(find /home/mattia/test/ -type f -name '*.*')
for f in $FILES
do
ext=${f#*.}
echo $ext
case "$ext" in
(mp4) echo "Keeping $f"
;;
(mkv) echo "Not deleting $f"
;;
(avi) echo "Holding on to $f"
;;
(*) rm -f "$f"
echo "deleted $f"
;;
esac
done
(which should work as long as your file names don't have spaces)
Or sorting-out the if-condition
[[ ! ( "$ext" = "mp4" || "$ext" = "mkv" || "$ext" = "avi" ) ]]
Upvotes: 0
Reputation: 124646
Aside from changing ||
to &&
, the script is fragile,
for example it won't work if any of the files contains spaces.
In general it's not safe to store the output of find
in a variable for looping, so this practice should be avoided.
In any case, you don't need a loop, find
can do this all by itself, and safer:
find /home/mattia/test/ -type f ! \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' \) -print -delete
Note that instead of !
, you could use the more intuitive -not
,
but keep in mind that it is not POSIX compliant.
Upvotes: 2