删除bash中除组外的所有文件

时间:2014-08-04 20:14:37

标签: arrays bash

我想删除所有文件,但是我在列表中删除了一个文件。让我们为了论证而说这些文件是在一个数组中。该数组仅包含文件的最后三位数字,不包含扩展名。所有文件都是扩展名jpg。这就是我一直在努力做的事情。文件名采用GEDC1227.JPG

的形式
pics=(227 222 231 248 252 253 255 272 274 278)
for line in *; do 
 for j in $pics[@]; do 
  [[ ${line:5:3} == $j ]] && break
 done
 rm $line
done

我知道有更简单的方法可以实现这一目标;但是,我有点好奇,为什么我的算法不起作用。我认为是因为每次都进入rm $行,而且当测试条件为真时我没有找到绕过该行的方法(对于我不想删除的文件)

2 个答案:

答案 0 :(得分:4)

你需要继续两次,即恢复外循环的下一次迭代:

pics=(227 222 231 248 252 253 255 272 274 278)
for line in *; do 
    for j in "${pics[@]}"; do 
        [[ ${line:5:3} == "$j" ]] && continue 2
    done
    rm -- "$line"
done
  • ${pics[@]}添加引号。不是必需的,但在元素扩展时防止单词拆分是一种很好的做法。
  • 引用==的第二个参数,以防止将其解释为glob模式。
  • --添加到rm,以防止尝试以-作为选项读取文件并导致rm错误。

此备选解决方案也可能适用但需要测试:

shopt -s extglob
shopt -s nullglob
echo rm -- ?????!(227|222|231|248|252|253|255|272|274|278)*

如果发现正确,请删除echo

来自bash手册的

continue

  

继续:继续[n]

     

恢复for,while或者循环。

     

恢复封闭FOR,WHILE或UNTIL循环的下一次迭代。   如果指定了N,则恢复第N个封闭循环。

答案 1 :(得分:0)

我也会考虑在没有循环的情况下这样做。

如果目录中有许多文件,可以使这样的东西并行运行并且不会阻塞(就像一个glob)。

pics=( 227 222 231 248 252 253 255 272 274 278 )

# convert the array to a regex that matches GEDC.227\.JPG$|GEDC.222\.JPG$|...
keep="$( echo "GEDC.${pics[@]}\\.JPG$" | sed -e 's: :\\.JPG$|GEDC.:g' )"

find -type f -iname GEDC*.jpg \
  | egrep -v "$keep" \
  | xargs rm