使用IF语句在Bash中使用嵌套的For循环

时间:2018-03-20 00:59:13

标签: bash shell for-loop nested

我有一个包含许多.cntl文件的目录 - 我使用For循环删除所有文件但是我想保留2个.cntl文件。这是我到目前为止的基本版本

MY_DIR=/home/shell/

CNTL_FILE_LIST=`find ${MY_DIR}*.cntl -type f`

CNTL_EXCEPTION_LIST="/home/shell/test4.cntl /home/shell/test5.cntl"

我在下面的嵌套For循环中遇到了一些语法问题。我试图删除MY_DIR中除test4.cntl和test5.cntl之外的所有cntl文件

for file in CNTL_FILE_LIST
do
  for exception in CNTL_EXCEPTION_LIST
  do
    if [ "${file}" != ${exception} ]
       rm $file
    fi
  done
done

谁能看到我做错了什么?

3 个答案:

答案 0 :(得分:3)

在实践中,您应find自己完成排除文件的工作,如the answer by user unknown 的第二部分(使用-not)所述。也就是说,为了证明人们如何安全地使用bash:

#!/usr/bin/env bash
case $BASH_VERSION in
  ''|[1-3].*) echo "ERROR: Bash 4.0 or newer required" >&2; exit 1;;
esac

# Use of lowercase names here is deliberate -- POSIX specifies all-caps names for variables
# ...meaningful to the operating system or shell; other names are available for application
# ...use; see http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html,
# fourth paragraph.
my_dir=/home/shell

# Using an associative array rather than a regular one allows O(1) lookup
declare -A cntl_exception_list
cntl_exception_list=(
  ["${my_dir}/test4.cntl"]=1
  ["${my_dir}/test5.cntl"]=1
)

while IFS= read -r -d '' file; do
  [[ ${cntl_exception_list[$file]} ]] && continue
  rm -f -- "$file"
done < <(find "$my_dir" -type f -print0)

注意:

  • declare -A创建一个关联数组。这些可以有任意字符串作为键;在这里,我们可以使用我们的名称再次匹配这些键。
  • 使用NUL分隔的文件名(-print0)可确保明确表示具有空格或文字换行符的名称。
  • 有关while read循环使用的语法,请参阅BashFAQ #1

答案 1 :(得分:1)

嗯file4.cntl是!= file5.cntl,因此在比较时删除了它,与file4.cntl相比,file5.cntl被删除。

MY_DIR=/home/shell/
CNTL_FILE_LIST=`find ${MY_DIR}*.cntl -type f`
CNTL_EXCEPTION_LIST="/home/shell/test4.cntl /home/shell/test5.cntl"

for file in CNTL_FILE_LIST
do
  for exception in CNTL_EXCEPTION_LIST
  do
    if [ "${file}" != ${exception} ]
       rm $file
    fi
  done
done

而是只使用find:

find ${MY_DIR} -maxdepth 1 -type f -name "*.cntl" -not -name "file4.cntl" -not -name "file5.cntl"  -delete 

但并非每个发现都支持-delete,Gnu-find,并且您必须知道,如果-maxdepth 1适用于您。

首先使用-ls而不是-delete。

答案 2 :(得分:0)

user unknow是对的。所以你可能不应该这样做。

相反,您可以在删除之前从$CNTL_EXCEPTION_LIST删除$CNTL_FILE_LIST

for i in $CNTL_EXCEPTION_LIST
do
        CNTL_FILE_LIST=${CNTL_FILE_LIST//$i/}
done

您可以参考man bash了解此用法,只需搜索Pattern substitution

在此之后,$ CNTL_FILE_LIST将不再包含例外,现在您可以通过rm $CNTL_FILE_LIST安全地删除它们。