代码之家  ›  专栏  ›  技术社区  ›  user2896120

仅通过特定路径获取唯一文件名

  •  -2
  • user2896120  · 技术社区  · 6 年前

    我有一个命令,我可以从中获取以2010开头的所有文件名的计数

    find folder_name/ -path '*/*/*/*/2010*'
    

    这很好,我得到了有效的结果。但是,假设我有这样的文件结构:

    */atl/apple/banana/20101004
    */atl/apple/oranges/20101004
    

    这将是同一类,因为两者都属于atl。所以不是计数是2,而是应该是1。有没有一种方法可以让我只为每个城市名称(atl)获取唯一的值?

    编辑

    find example/ -path '*/*/*/*/2010*'
    

    我得到的结果是:

    example/atl/apples/bananas/20100510 //1 instance of this date in atl
    example/atl/apples/oranges/20100510 //This date is a duplicate and should not be counted
    example/nyc/apples/bananas/20100510 //1 instance of this date in nyc
    example/nyc/apples/bananas/20100511 //1 instance of this date in nyc
    example/bkg/apples/bananas/20100510 //1 instance of this date in bkg
    

    4 回复  |  直到 6 年前
        1
  •  0
  •   Charles Duffy    6 年前

    除了 find 在原生bash中(而不是依赖外部工具)可能如下所示。


    根据问题中描述的设置:

    mkdir -p example/{atl,nyc,bkg}/apples/{bananas,oranges}
    touch \
      example/atl/apples/bananas/20100510 \
      example/atl/apples/oranges/20100510 \
      example/nyc/apples/bananas/20100510 \
      example/nyc/apples/bananas/20100511 \
      example/bkg/apples/bananas/20100510
    

    …实施:

    #!/usr/bin/env bash
    case $BASH_VERSION in ''|[123].*) echo "ERROR: Bash 4.0 needed" >&2; exit 1;; esac
    
    declare -A seen=( )
    
    while IFS= read -r -d '' name; do
      name=${name#example/}  # ignore the leading example/
      first_piece=${name%%/*}
      last_piece=${name##*/}
      seen[${first_piece}/${last_piece}]=1
    done < <(find example -type f -print0)
    
    echo "Number of distinct first/last pairs: ${#seen[@]}"
    echo "Those individual pairs are:"
    printf ' - %s\n' "${!seen[@]}"
    

    Number of distinct first/last pairs: 4
    Those individual pairs are:
     - atl/20100510
     - bkg/20100510
     - nyc/20100510
     - nyc/20100511
    
        2
  •  0
  •   Graeme    6 年前

    awk 要仅选择城市名称和文件名字段,可以通过管道发送到 sort -u ,那么 wc

    find folder_name/ -path '*/*/*/*/2010*' |
        awk -F/ '{ print $2, $5 }' |
        sort |
        uniq -c
    
        3
  •  0
  •   agc Blair Houghton    6 年前

    使用 sort wc 数一数,然后 bash 工艺替代 为了让它看起来更好:

    find folder_name/ -path '*/*/*/*/2010*' | 
    sort -t '/' -k 2,2 -k 5,5 -u | tee >(echo "Count: $(wc -l)")
    

    “结果” 样本数据):

    example/atl/apples/bananas/20100510
    example/bkg/apples/bananas/20100510
    example/nyc/apples/bananas/20100510
    example/nyc/apples/bananas/20100511
    Count: 4
    

    cut tee :

    find folder_name/ -path '*/*/*/*/2010*' | 
    sort -t '/' -k 2,2 -k 5,5 -u | cut -d '/' -f 2,5 | tee >(echo "Count: $(wc -l)")
    

    atl/20100510
    bkg/20100510
    nyc/20100510
    nyc/20100511
    Count: 4
    

    工作原理:

    1. find
    2. 分类 要按第2和第5字段排序,只打印唯一的城市/日期行。请注意 -k -k 2,5 不会以同样的方式工作。
    3. 厕所
        4
  •  0
  •   Jordan LE NUFF    6 年前

    通过@charles激励我,我创建了以下结构:

    mkdir -p example/{atl,nyc,bkg}/apples/{bananas,oranges}
    touch \
    example/atl/apples/bananas/20100510 \
    example/atl/apples/oranges/20100510 \
    example/nyc/apples/bananas/20100510 \
    example/nyc/apples/bananas/20100511 \
    example/bkg/apples/bananas/20100510 \
    example/bkg/coconuts/bananas/20100510
    

    然后,假设您认为一个文件是重复的,因为它在同一个文件中 二级 子目录(apples或coconuts),我建议使用以下命令:

    for i in $(find example -maxdepth 2 -mindepth 2 -type d); do find $i -path '*/*/*/*/2010*'|awk -F\/ '{print $NF}'|sort -u;done|wc -l
    

    5
    

    如果你想要的是一个相同的文件,那就认为它是重复的 子目录(atl、nyc或bkg),然后使用以下命令:

    for i in $(find example -maxdepth 1 -mindepth 1 -type d); do find $i -path '*/*/*/*/2010*'|awk -F\/ '{print $NF}'|sort -u;done|wc -l
    

    4