我必须处理多个没有完整名称的文件。我正在使用通配符运行 if 语句。例如...
if [ "ESGSN_*.SMS.EDR" ]; then
echo "There are files to process in this run"
for F in ESGSN_*.SMS.EDR; do
gzip < "$F" > "$F.gz"
done
fi
如果有多个文件或单个文件,这将起作用并压缩它们。但如果没有文件,它仍然会运行 zip 而不是直接结束。我想知道是否有什么方法可以让它完成并继续。
我尝试在文件名之前的括号内使用运算符“-f”和“-a”,但这些会出错:“需要二元运算符”
由于某种原因,文件名中的星号没有显示在消息下方。因此文件名是“ESGSN_”*“.SMS.EDR”,其中双引号是星号。
答案1
if ! gzip ESGSN_*.SMS.EDR 2>/dev/null; then
printf 'No files to process (gzip exit code: %d)\n' "$?"
fi
由于字符串ESGSN_*.SMS.EDR
非空,因此您的测试将始终为真。当glob*
用双引号引起来时,不会被处理。
另外,如果模式不匹配任何内容,大多数 shell 默认情况下会保留未展开的模式,这在您的情况下意味着您的代码最终将创建一个空文件,ESGSN_*.SMS.EDR.gz
如果模式不匹配任何文件名,则调用。
上面的代码将简单地尝试压缩与该模式匹配的所有文件,如果失败,则会打印一条消息。
答案2
有两种方法可以回答这个问题:修复当前脚本,或提出更快、更精确的替代方案。我会尝试这两种方法 :)
首先,你的脚本的一个问题是,它[ "ESGN_*.SMS.EDR" ]
总是会被评估为 true。该[ "<string>" ]
构造只是测试字符串是否非空。即使没有文件,您给出的字符串也不是空的,因此测试不会执行任何操作。
要修复它,您需要做的是循环所有文件并测试它们是否与模式匹配。以下对我有用:
for F in *; do
if [[ "$F" =~ ESGSN_.*\.SMS\.EDR ]]; then
printf "Processing '%s'\n" "$F"
gzip < "$F" > "$F.gz"
fi
done
然而,如果我想解决这个问题供我自己使用,那并不是我真正会做的。相反,使用 GNU 更快、更自然find
,它可以轻松进行模式匹配:
find ./ -type f -regex ".*/ESGSN_.*\.SMS\.EDR" -exec bash -c "gzip < {} > {}.gz" \;
该find
命令非常强大,如果您要经常使用 Linux,您会希望熟悉它。我建议仔细看一下man find
。
答案3
感谢大家。我能够从以下地方获得我需要的东西:
if ls -lrt ESGSN_*.SMS.EDR ; then
答案4
所以我为你简化了一些。
#!/bin/bash
shopt -s nullglob
files=(yourdir/*)
if [[ ${#files[@]} == 0 ]] # If array is equal to 0
then echo "No files there" >&2
exit 1
else
gzip "${files[@]}" # gzip all elements within the array.
fi
shopt -u nullglob
解释一下脚本的作用:
设置nullglob
方式shopt -s nullglob
nullglob 用于对与模式匹配的文件进行计数。如果没有 nullglob,glob * 将扩展为文字 * ,这意味着在空目录中计数将始终 > 1,从而导致错误计数。
取消设置nullglob
通过shopt -u nullglob
如果此行之后有更多可能受 影响的代码,这一点很重要
nullglob
。