根据模式清单匹配文件

问题描述 投票:0回答:3

我想检查某些文件是否与清单文件中声明的模式匹配。例如,以下文件

A_cycles.pdf
A_filter_passed_vs_occupied.pdf
A_grouped_cycle.csv
A_grouped_lane.csv
A_grouped_lane_cycle.csv
A_metadata.csv
A_percent_q30.pdf
A_raw.csv
seqrun_A.json

应对照此清单进行检查

*_grouped_cycle.csv
*_grouped_lane.csv
*_grouped_lane_cycle.csv
*_metadata.csv
*_raw.csv
seqrun_*.json

这是我的代码:

while IFS= read -r pattern; do
    # Modify the pattern to match filenames without needing to escape dot characters
    modified_pattern="${pattern//./[.]}"
    # Convert the modified pattern to a regular expression
    regex_pattern="^${modified_pattern//\*/.*}"
    # Check if the filename matches the pattern using regular expressions
    if [[ "$filename1" =~ $regex_pattern ]]; then
        included=true
        echo "Filename $(basename "$filename1") matched pattern $pattern in MANIFEST"
        break
    fi
done < <(grep -v '^#' "$MANIFEST_FILE")

这是输出:

Filename A_grouped_cycle.csv matched pattern *_grouped_cycle.csv in MANIFEST
Filename A_grouped_lane.csv matched pattern *_grouped_lane.csv in MANIFEST
Filename A_grouped_lane_cycle.csv matched pattern *_grouped_lane_cycle.csv in MANIFEST
Filename A_metadata.csv matched pattern *_metadata.csv in MANIFEST
Filename A_raw.csv matched pattern *_raw.csv in MANIFEST

几乎可以工作,但我不知道为什么

seqrun_A.json
seqrun_*.json
不匹配。

我尝试了几种方法但没有成功。这种方法应该以类似的方式与 MANIFEST 文件中声明的任何类型的模式一起工作/匹配(基本上使用 *)。

顺便说一句,这包含在 Gitlab CI 作业中

bash shell unix gitlab-ci
3个回答
0
投票

假设 MANIFEST 包含 glob 模式。

未加引号的扩展经历分词和文件名扩展。懒惰的答案就是:

shopt -s nullglob
echo $(cat MANIFEST)

这会导致分词。使用 bash,我们将使用

compgen -G
将 glob 扩展到文件列表。

readarray -t patterns <MANIFEST
compgen -G "${patterns[@]}"

0
投票

这假设有效:

while IFS= read -r pattern; do
    # Check if the filename matches the pattern using fnmatch
    if [[ "$(basename "$filename1")" == $pattern ]]; then
        included=true
        echo "Filename $(basename "$filename1") matched pattern $pattern in MANIFEST"
        break
    fi
done < <(grep -v '^#' "$MANIFEST_FILE")

简单地使用“==”,但我不明白为什么。 UNIX 会自动比较字符串和通配符吗?

更新/说明

Bash 条件表达式中的

==
运算符
([[ ... ]])
支持模式匹配,包括 glob 模式。这不是 Unix 原生的,而是 Bash 本身提供的功能。

当您在

==
中使用
[[ ... ]]
时,如果比较的右侧包含
*
?
等通配符,Bash 会将其视为模式。此行为允许您直接在条件表达式中执行模式匹配,而不需要额外的命令或函数。

在您的情况下,当您使用

$(basename "$filename1")
$pattern
==
进行比较时,由于
$pattern
字符的存在,Bash 会将 * 识别为
glob 模式
,并相应地执行模式匹配。这允许您直接在脚本中将文件名与 glob 模式进行匹配,而无需求助于外部工具或函数。


0
投票

这可能就是你想要的:

$ cat tst.sh
#!/usr/bin/env bash

shopt -s nullglob

manifest_file='manifest_globs.txt'
readarray -t glob_pats < "$manifest_file"

for filename; do
    for glob_pat in "${glob_pats[@]}"; do
        if [[ $filename == $glob_pat ]]; then
            echo "$filename matched $glob_pat"
        fi
    done
done

$ ./tst.sh A_cycles.pdf A_filter_passed_vs_occupied.pdf A_grouped_cycle.csv A_grouped_lane.csv A_grouped_lane_cycle.csv A_metadata.csv A_percent_q30.pdf A_raw.csv seqrun_A.json
A_grouped_cycle.csv matched *_grouped_cycle.csv
A_grouped_lane.csv matched *_grouped_lane.csv
A_grouped_lane_cycle.csv matched *_grouped_lane_cycle.csv
A_metadata.csv matched *_metadata.csv
A_raw.csv matched *_raw.csv
seqrun_A.json matched seqrun_*.json
© www.soinside.com 2019 - 2024. All rights reserved.