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

按文件扩展名统计用户组文件数:Bash脚本异常求解决

问题排查:按文件扩展名统计用户组文件数量的Bash脚本修正

我需要完成一个练习:写一个脚本,对目录里的普通文件按扩展名分类,列出每个扩展名对应的、拥有至少一个该扩展名文件的用户组,以及各组的文件数量。

示例输入

-rw-------  2   utente1   staff   4096  2007-02-10   14:28   doc1.pdf
-rw-r--r--  1   utente1   staff    102  2007-02-11   02:05   doc2.pdf
-rw-r--r--  1   utente2   users   3145  2007-01-16   01:48   rel.tex
-rw-------  1   utente2   users    268  2007-01-16   10:37   song1.mp3
-rw-r--r--  4   utente3   staff   4096  2006-04-28   19:29   text1.tex
-rw-r--r--  1   utente3   staff     11  2007-05-02   12:10   text2.tex

预期输出

.tex: users 1 staff 2
.pdf: staff 2
.mp3: users 1

我的错误脚本

我写的Bash脚本运行异常,会输出不存在的数值,求修正:

#!/bin/bash

groups=$(awk ' {print $4}' group.txt | sort | uniq)

echo .tex:
for group in $groups
do
    awk -v gr=$group ' ($4==gr && $1~"^-") {somma=somma+$5; num=num+1}; END {if(somma!=0) {print gr,num,"("somma")"}}' group.txt

done


echo .pdf:
for group in $groups
do
    awk -v gr=$group ' ($4==gr && $1~"^-") {somma=somma+$5; num=num+1}; END {if(somma!=0) {print gr,num,"("somma")"}}' group.txt 
done


echo .mp3:
for group in $groups
do
    awk -v gr=$group ' ($4==gr && $1~"^-") {somma=somma+$5; num=num+1}; END {if(somma!=0) {print gr,num,"("somma")"}}' group.txt
done

问题分析

你的脚本存在几个核心问题:

  1. 未过滤对应扩展名文件:只判断了普通文件和用户组匹配,但完全没筛选对应扩展名,导致统计的是该组所有普通文件的数量,不是目标扩展名的。
  2. 逻辑冗余重复:每个扩展名单独写循环,重复执行相同逻辑,效率低且易出错。
  3. 多余统计文件大小:需求只需要文件数量,脚本里统计的$5(文件大小)属于额外计算,还干扰输出格式。
  4. 输出格式不符预期:预期是每个扩展名一行,后面跟所有符合条件的组和数量,你的脚本会每个组单独输出一行。

修正后的脚本

直接用awk一次性处理所有逻辑,高效又简洁:

#!/bin/bash

# 若要处理当前目录真实文件,可将group.txt替换为find . -maxdepth 1 -type f -ls
awk '
# 仅处理普通文件
$1 ~ /^-/ {
    # 提取扩展名:拆分文件名,取最后一个.后的部分,无扩展名则跳过
    split($NF, name, /\./)
    if (length(name) > 1) {
        ext = "." name[length(name)]
        # 统计每个扩展名+用户组的文件数量
        count[ext, $4]++
    }
}
END {
    # 收集所有唯一扩展名
    for (key in count) {
        split(key, arr, SUBSEP)
        exts[arr[1]] = 1
    }
    # 按扩展名输出对应组和数量
    for (ext in exts) {
        printf "%s:", ext
        for (group in count) {
            split(group, arr, SUBSEP)
            if (arr[1] == ext) {
                printf " %s %d", arr[2], count[group]
            }
        }
        printf "\n"
    }
}
' group.txt

修正说明

  • 扩展名提取:用split拆分文件名,取最后一个.后的字段,能正确处理带多个.的文件名(比如a.b.txt会提取.txt)。
  • 统计逻辑:用二维关联数组count[ext, $4]++直接统计,避免重复遍历文件。
  • 输出格式:先收集所有扩展名,再逐个输出对应的组和数量,完全匹配预期格式。
  • 灵活性:如果要处理当前目录的真实文件,把group.txt替换为find . -maxdepth 1 -type f -ls(比ls -l更可靠,避免文件名含空格的问题)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 18:05:01