【问题标题】:bash, list filenames, arraybash,列出文件名,数组
【发布时间】:2015-03-01 17:31:00
【问题描述】:

我有一个类似的目录结构

$ ls /comp/drive/
2009  2010  2011  2012  2013  2014

$ ls 2009
01  02  03  04  05  06  07  09  10  11  12

$ ls 2013
01  02  04  05  06  08  09  10  12

$ ls 2013/04/*.nc
file4.nc file44.nc file45.nc file49.nc

有几年这样的目录,每年有几个月的目录,里面是.nc文件。

我想要做的是获取提供的开始和结束年份/月份的文件名数组。

例如sYear=2011; eYear=2013; sMonth=03; eMonth=08

所以,我只想获取从 2011/03 年到 2013/08 年所有文件名的数组,而不进入目录。

任何 bash 技巧?

【问题讨论】:

    标签: arrays bash for-loop filenames


    【解决方案1】:
    sYear=2011; eYear=2013; sMonth=03; eMonth=08
    
    # prevent bugs from interpreting numbers as hex
    sMonth=$(( 10#$sMonth ))
    eMonth=$(( 10#$eMonth ))
    
    files=( )
    for (( curYear=sYear; curYear <= eYear; curYear++ )); do
      # include only months after sMonth
      for monthDir in "$curYear"/*/; do
        [[ -e $monthDir ]] || continue # ignore years that don't exist
        curMonth=${monthDir##*/}
        (( curMonth )) || continue     # ignore non-numeric directory names
        (( curYear == sYear )) && (( 10#$curMonth < sMonth )) && continue
        (( curYear == eYear )) && (( 10#$curMonth > eMonth )) && continue
        files+=( "$monthDir"/*.nc )
      done
    done
    
    printf '%q\n' "${files[@]}"
    

    【讨论】:

    • 谢谢查尔斯,我得到了这个sMonth=(( 10#sMonth )) -bash: syntax error near unexpected token `(' 另外,最好在最后的 ${files[@ ]}。很抱歉再次打扰。
    • 需要sMonth=$((10#sMonth))((sMonth = 10#sMonth))。在真正的控制台上时会更完整地回答。
    • @user3652962,“完整”路径是指绝对路径吗?唯一需要的更改是将"$curYear"/*/ 更改为"$PWD/$curYear"/*/
    【解决方案2】:

    试试这个:

    sYear=2011
    sMonth=03
    
    eYear=2013
    eMonth=08
    
    shopt -s nullglob
    declare -a files
    
    for year in *; do
        (( ${year} < ${sYear} || ${year} > ${eYear} )) && continue
    
        for year_month in ${year}/*; do
    
            month=${year_month##*/}
            (( ${year} == ${sYear} && ${month##0} < ${sMonth##0} )) && continue;
            (( ${year} == ${eYear} && ${month##0} > ${eMonth##0} )) && continue;
    
            files+=(${year_month}/*.nc)
        done
    done
    
    echo "${files[@]}"
    # printf "$(pwd)/%q\n" "${files[@]}" # for full path
    

    【讨论】:

    • 首先——见mywiki.wooledge.org/ParsingLs。其次,08 被视为 octal,而不是 decimal,因此这是错误的,因为月份编号高于 7 但低于 10。第三,使用未引用的 @987654324 @ 几乎总是错误的事情——如果你有带空格的文件名,它们会被分解成单独的参数,如果你有一个文件名中的 * 被空格包围,那么这个 glob 实际上会被扩展。引用"${files[@]}" 是正确的。
    • 这里也不完全正确 - glob 表达式不能在引号中,即使扩展应该是。你想要files+=( "${year}/${month}/"*.nc ),或者类似的东西。 (在这种情况下,大括号是严格可选的)。
    • @CharlesDuffy,我只是举了一个简单的例子。并没有实际测试。感谢您发现错误——我已修复它们。
    • 点头。我想你比我早 6 秒发布了你的答案,他们当然有很多共同点。并行开发就是这么有趣。
    • @user3652962,我对其进行了调整以返回相对于当前目录的路径。如果您想要完整路径,请取消注释最后一行 printf
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    相关资源
    最近更新 更多