You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何筛选目录中不含指定文本的文件名?脚本异常求助

问题

我正在运行若干实验,结果会输出到对应文件里。实验成功的话,文件内会包含ChampSim completed all CPUs文本,我需要筛选出未成功的案例——也就是不含这句话的文件,不同实验结果靠文件名区分。

我的思路是用ls拿所有文件名,grep筛出成功的文件,再通过数组差集得到失败文件名,但运行脚本时总是输出所有文件名。

已经做了这些排查:

  • 用简单数组验证差集逻辑,结果是对的
  • 单独输出所有文件名或成功文件名,结果也都正确
  • 但完整运行下面的脚本时,始终输出所有文件名:
CURRENT_DIR=$(cd $(dirname $0); pwd)
ChampSim_path=$CURRENT_DIR/..
cd $CURRENT_DIR/$1


all=$(ls -q * | wc -l)

good=$(grep "ChampSim completed all CPUs" * | wc -l)

good_trace_prefetcher=($(grep  -Rl "ChampSim completed all CPUs" *  ))

all_trace_prefetcher=($(ls -q * ))

# echo  ${good_trace_prefetcher[@]}
# echo   ${all_trace_prefetcher[@]}

# exit
# arry_list1=(1 2 3 4 5 6 7 8 9)
# arry_list2=(3 5 8)

arry_list1=${all_trace_prefetcher[@]}
arry_list2=${good_trace_prefetcher[@]}
 
declare -a diff_list
t=0
flag=0

# echo arry_list1=${arry_list1[@]}
# echo arry_list2=${arry_list2[@]}
 
for list1_num in "${arry_list1[@]}"
do
    # echo list1_num is ${list1_num}
    for list2_num in "${arry_list2[@]}"
    do
        # echo list2_num is ${list2_num}
        if [[ "${list1_num}" == "${list2_num}" ]]; then
            flag=1
            break
        fi
    done
    if [[ $flag -eq 0 ]]; then
        diff_list[t]=$list1_num
        t=$((t+1))
    else
        flag=0
    fi
done
echo diff_list=${diff_list[@]}
问题原因

核心错误是数组赋值时丢了数组结构:

arry_list1=${all_trace_prefetcher[@]}
arry_list2=${good_trace_prefetcher[@]}

不加双引号直接用${array[@]}赋值,数组会被展开成一个长字符串,所有元素用空格拼接。后续遍历"${arry_list1[@]}"时,其实是在遍历这一个长字符串,而非数组的每个单独元素。内层循环的比较永远匹配不上,所有元素都被塞进了差集里。

修复方案

1. 修正数组赋值方式

把数组赋值改成保留数组结构的写法,加双引号和括号:

arry_list1=("${all_trace_prefetcher[@]}")
arry_list2=("${good_trace_prefetcher[@]}")

这样arry_list1和arry_list2才会被正确识别为数组,遍历的时候能拿到每个单独的文件名。

2. 优化后的完整脚本

CURRENT_DIR=$(cd $(dirname $0); pwd)
ChampSim_path=$CURRENT_DIR/..
# 增加目录切换失败的退出逻辑,避免后续命令跑错目录
cd "$CURRENT_DIR/$1" || exit  

# 获取所有文件数组
all_trace_prefetcher=($(ls -q *))
# 获取成功的文件数组
good_trace_prefetcher=($(grep -Rl "ChampSim completed all CPUs" *))

# 正确复制数组结构
arry_list1=("${all_trace_prefetcher[@]}")
arry_list2=("${good_trace_prefetcher[@]}")

declare -a diff_list
t=0

for list1_num in "${arry_list1[@]}"
do
    flag=0
    for list2_num in "${arry_list2[@]}"
    do
        if [[ "${list1_num}" == "${list2_num}" ]]; then
            flag=1
            break
        fi
    done
    if [[ $flag -eq 0 ]]; then
        diff_list[t]="$list1_num"
        t=$((t+1))
    fi
done

echo "未成功的实验文件:"
echo "${diff_list[@]}"

3. 更简洁的实现方式

其实不用手动做数组差集,grep本身就支持反向筛选,效率更高:

CURRENT_DIR=$(cd $(dirname $0); pwd)
ChampSim_path=$CURRENT_DIR/..
cd "$CURRENT_DIR/$1" || exit

# 直接输出不包含目标字符串的文件
grep -RL "ChampSim completed all CPUs" *

-L参数会直接返回不匹配的文件名,比手动处理数组简单得多。

内容的提问来源于stack exchange,提问作者Gerrie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 13:17:23