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

Bash技巧:如何每次提取3个文件的父目录名称

问题与解决方案

需求说明

现有一批文件路径,需要完成以下操作:

  1. 按字母顺序排序文件路径
  2. 每3个文件路径为一组
  3. 提取每组中每个文件的父文件夹名称
  4. 命令需支持含空格的路径

原始路径示例:

/foo/bar/bazz/JMA01023D_E07/JMA01023D_E07_EKDL230054768-1A_22HFKNLT3_L4_1.fq.gz
/foo/bar/bazz/JMA01023D_E08/JMA01023D_E08_EKDL230054768-1A_22HFKNLT3_L4_1.fq.gz
/foo/bar/bazz/JMA01023D_E09/JMA01023D_E09_EKDL230054768-1A_22HFKNLT3_L4_1.fq.gz
/foo/bar/bazz/JMA01022D_E06/JMA01022D_E06_EKDL230054767-1A_22HF2WLT3_L7_1.fq.gz
/foo/bar/bazz/JMA01001D_A01/JMA01001D_A01_EKDL230054750-1A_222T7MLT4_L1_1.fq.gz
/foo/bar/bazz/JMA01001D_A02/JMA01001D_A02_EKDL230054750-1A_222T7MLT4_L1_1.fq.gz

期望输出:

JMA01001D_A01 JMA01001D_A02 JMA01022D_E06
JMA01023D_E07 JMA01023D_E08 JMA01023D_E09

可行解决方案

方案1:纯Awk处理(推荐,简洁且支持空格)

find "$@" -iname '*_1.fq.gz' -print0 | sort -z | awk -v RS='\0' '{
    # 移除文件名,得到父目录完整路径
    sub(/\/[^\/]+$/, "", $0)
    # 移除父目录前的所有路径,仅保留目录名
    sub(/.*\//, "", $0)
    # 将目录名存入数组
    arr[NR] = $0
}
END {
    # 按每3个一组输出
    for (i=1; i<=NR; i++) {
        printf "%s%s", arr[i], (i%3==0 ? "\n" : " ")
    }
    # 处理最后一组不足3个的情况,补换行
    if (NR%3 != 0) print ""
}'

方案2:结合dirname、basename与xargs

find "$@" -iname '*_1.fq.gz' -print0 | sort -z | \
xargs -0 -n1 sh -c 'basename "$(dirname "$1")"' _ | \
xargs -0 -n3 awk '{printf "%s ", $0} END{print ""}'
  • 步骤解析:
    1. dirname "$1" 获取文件的父目录完整路径
    2. basename 提取父目录的名称
    3. xargs -n3 每3个目录名一组,用Awk格式化为空格分隔的行

方案3:Awk分割路径数组实现

find "$@" -iname '*_1.fq.gz' -print0 | sort -z | awk -v RS='\0' -v ORS=' ' '{
    # 按/分割路径,取倒数第二个元素(父文件夹名)
    split($0, path_parts, "/")
    dir_name = path_parts[length(path_parts)-1]
    print dir_name
    # 每3个输出后换行
    if (NR % 3 == 0) {
        print "\n"
        ORS = " "
    }
}' | sed -z '$ s/ $/\n/'
  • 最后用sed移除末尾多余的空格并补换行,保证输出格式整洁

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 13:34:56