我有一个bash脚本,应该不是.avi,.mp4和.mkv的所有文件。
这是我试过的:
#!/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
但是这个脚本删除了所有的文件。
除了改变||
到&&
,脚本是脆弱的,例如,如果任何文件包含空格,它将无法正常工作。 一般来说,将find
的输出存储在循环变量中是不安全的,所以应该避免这种做法。
无论如何,你不需要循环, find
可以自己做这一切,更安全:
find /home/mattia/test/ -type f ! \( -name '*.mp4' -o -name '*.mkv' -o -name '*.avi' \) -print -delete
请注意,而不是!
,你可以使用更直观的-not
,但请记住,它不是POSIX兼容。
这是合乎逻辑的
[[ "$ext" != "mp4" || "$ext" != "mkv" || "$ext" != "avi" ]]
总是如此。 例如:如果文件名是movie.avi
, "$ext" != "mp4"
将是真的,因此完整的if总是为真。
一如往常,有很多方法可以解决这个问题。 雅诺斯find
; 另一种选择是:
find /find /home/mattia/test/ -type f -name '*.*'home/mattia/test/ -type f -name '*.*' | egrep -v '.mp4$|.mkv$|.avi$' | xargs rm
或者,在你的循环中:
#!/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
(只要你的文件名没有空格就应该工作)
或者整理if条件
[[ ! ( "$ext" = "mp4" || "$ext" = "mkv" || "$ext" = "avi" ) ]]