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

如何循环浏览两个目录中已排序的文件名列表

  •  3
  • v010dya  · 技术社区  · 6 年前

    请注意,我读过如下条目 For loop for files in multiple folders - bash shell 他们要求的是一件截然不同的事情。

    我想按排序顺序遍历存在于两个目录中的任何一个目录中的文件名。文件中可能包含空格。

    假设我有:

    1/
      a
      a c b
      b
      c
    2/
      a
      d
    

    我想循环:'a','a c b','b','c','d'。

    我已尝试执行以下操作:

    for fname in $((ls -1 -f -A "${dir1}"; ls -1 -f -A "${dir2}")|sort --unique); do
      echo "testing ${fname}"
    done
    

    结果是

    testing .
    testing ..
    testing a
    testing a
    testing c
    testing b
    testing b
    testing c
    testing d
    

    无论什么原因,我都会得到“.”和“…”我试图排除的条目 -A ,并且文件“a c b”被分解为三个字符串。

    我试图通过添加 --zero sort 命令,没有任何改变;引用整体 $(ls...|sort) 部分,并导致for循环中的一个条目,该条目接收了整个字符串,其中包含多行,每行都包含filename。

    3 回复  |  直到 6 年前
        1
  •  4
  •   Inian    6 年前

    永远不要有意识地分析的输出 ls 命令(请参见 Why you shouldn't parse the output of ls(1) ),它有很多潜在的陷阱。使用 find 命令及其 -print0 选项对文件进行null分隔,以便处理带有空格/换行符或任何元字符的文件名,并随后使用GNU sort 使用相同的空分隔符,按字母顺序对其排序(&删除重复文件。如果 dir1 dir2 是包含要查找的文件夹名称的shell变量,您可以执行以下操作

    while IFS= read -r -d '' file; do
        printf '%s\n' "$file"
    done< <(find "${dir1}" "${dir2}" -maxdepth 1 -type f -printf "%f\0" | sort -t / -u -z) 
    
        2
  •  2
  •   tripleee    6 年前

    一种更简单的方法可能是遍历所有内容并通过其他方式排除重复项。

    #!/bin/bash
    # Keep an associative array of which names you have already processed
    # Requires Bash 4
    declare -A done
    for file in 1/* 2/*; do
        base=${file#*/}  # trim directory prefix from value
        test "${done[$base]}" && continue
        : do things ...
        done["$base"]="$file"
    done
    
        3
  •  1
  •   Yaniv Shaked    6 年前

    答复:

    1. 将for分隔符从空白更改为 \n 使用以下命令:

      IFS=$'\n'
      
    2. 您使用 -l 对于ls,这意味着 -a (和覆盖 -A ); 使用 --color=never 相反

    总结如下:

    IFS=$'\n'
    for fname in $((ls -1 --color=never -A "${dir1}"; ls -1 --color=never -A "${dir2}")|sort --unique); do
      echo "testing ${fname}"
    done