use*_*627 2 shell bash wildcards test pattern-matching
假设我生成了两个目录,每个目录中都有文本文件,如下所示
mkdir "Directory1"
mkdir "Directory2"
touch "Directory1/fileclass1_"{1..5}".txt"
touch "Directory1/fileclass2_"{1..5}".txt"
touch "Directory2/fileclass1_"{1..5}".txt"
touch "Directory2/fileclass2_"{1..5}".txt"
Run Code Online (Sandbox Code Playgroud)
假设我通过执行以下操作来验证所有文件都在里面
A=( "Directory1" "Directory2" )
B=( "fileclass1" "fileclass2" )
for a in "${A[@]}"; do
for b in "${B[@]}"; do
for i in {1..5}; do
name="${a}/${b}*${i}.txt"
[[ ! -e $name ]] && echo "$name Does Not Exist"
done
done
done
Run Code Online (Sandbox Code Playgroud)
这返回
Directory1/fileclass1*1.txt Does Not Exist
Directory1/fileclass1*2.txt Does Not Exist
...
Run Code Online (Sandbox Code Playgroud)
但是,如果我用单括号替换双括号,我得到
A=( "Directory1" "Directory2" )
B=( "fileclass1" "fileclass2" )
for a in "${A[@]}"; do
for b in "${B[@]}"; do
for i in {1..5}; do
name="${a}/${b}*${i}.txt"
[ ! -e $name ] && echo "$name Does Not Exist"
done
done
done
Run Code Online (Sandbox Code Playgroud)
它什么也不返回,表明所有文件确实都在那里。
为什么在这种情况下,双括号失败,而单括号有效?我假设我应该始终使用双括号,字符串匹配中的通配符是否创建了我不应该拥有的东西?
条件运算符-e测试给定名称的文件是否存在。它不进行任何模式匹配。[[ -e fileclass1*1.txt ]]测试是否存在fileclass1*1.txt名称中带有星号的文件,而不是测试是否至少有一个与通配符模式匹配的文件fileclass1*1.txt。
对于单括号[ ! -e $name ],由于$name未加引号,因此 的值name会经历通配符替换和分词。name如果的值为Directory1/fileclass1*1.txt,则效果取决于有多少个文件与通配符模式匹配。
-e操作员看到文件名Directory1/fileclass1*1.txt不存在,所以[ ! -e $name ]是true。-e操作员看到该文件名存在\xc2\xb9,因此[ ! -e $name ]为 false。[ ! -e $name ]显示错误消息并返回失败状态。效果不同,[[ -e $name ]]因为[[ \xe2\x80\xa6 ]]是特殊语法(而[是参数正常扩展的普通命令)。内部没有进行分词或通配符扩展[[ \xe2\x80\xa6 ]]。
要解决您的实际问题,请参阅测试是否存在与模式匹配的文件以执行脚本
\n\xc2\xb9除非在不太可能的情况下,由于竞争条件,否则在 shell 列出目录内容以扩展通配符模式的时间和操作员-e检查文件是否存在的时间之间,文件将被删除。