使用 if 语句使用通配符查看文件是否位于文件夹中

使用 if 语句使用通配符查看文件是否位于文件夹中

我必须处理多个没有完整名称的文件。我正在使用通配符运行 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

相关内容