代码之家  ›  专栏  ›  技术社区  ›  Karel Bílek

如何使用时间修改顺序安全地迭代glob?

  •  0
  • Karel Bílek  · 技术社区  · 3 年前

    目前,我正在bash脚本中执行此操作。

    for i in $(ls -tr *.tar); do
    # something
    done
    

    当我跑步时 shellcheck ,我得到了(正确的)警告

    for i in $(ls -tr *.tar); do
             ^-------------^ SC2045 (warning): Iterating over ls output is fragile. Use globs.
    

    好吧,但在这里该怎么办?我不会用地球仪,或者至少我不知道怎么用。

    我会加上我 需要 保持订单 ls -tr 确实,也就是说,按时间修改(并反转,最新在底部)排序。

    我已经看到了一些实现这一点的方法,其中一些是在Stack Overflow上(例如 In a bash script how to loop through files sorted by date ),正在执行find/sort/awk组合,但这一切似乎比使用更脆弱 ls 。

    有没有 安全 怎么做?(我使用的是带有“标准”coreutils等的Linux)

    2 回复  |  直到 3 年前
        1
  •  2
  •   Charles Duffy    3 年前

    在很大程度上,这是由 BashFAQ #3 ;下面提取相关的子集。


    在GNU系统上, find 的 -printf 可以打印时间戳元数据。

    使用NUL分隔的输出和 sort -z 确保对所有可能的文件名(包括包含文本换行符的文件名)进行正确操作(NUL是唯一不可能存在于所有UNIXy系统的路径中的字符)。

    while IFS= read -r -d : time && IFS= read -r -d '' file; do
      echo "Read ${file} with timestamp ${time}"
    done < <(find "$dir" -mindepth 1 -maxdepth 1 -type f -printf '%T@:%p\0' | sort -zn)
    

    使用 -printf 确保了定义良好的输出格式,因此(再次假设GNU工具的可用性)一点也不脆弱。

    如果要颠倒顺序并从最新到最旧列出,请添加 -r 的论点 sort 。

        2
  •  -1
  •   jmvcollaborator    3 年前

    正确的方式:

    for i in *.tar
    do
    [[ -e "$i" ]] || break  # handle the case of no *.tar files
      echo "$i"
    done
    
    推荐文章