我有一个包含许多.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
谁能看到我做错了什么?
答案 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
创建一个关联数组。这些可以有任意字符串作为键;在这里,我们可以使用我们的名称再次匹配这些键。-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
安全地删除它们。