按日期对 bash 中的文件数组列表进行排序并绕过参数限制

按日期对 bash 中的文件数组列表进行排序并绕过参数限制

因此,我在 bash shell 中有一个文件数组列表,我想按修改日期对数组中的所有文件进行排序,从最旧的文件开始是数组中的第一个文件。但是,我不想对原始数组进行排序和修改,而是希望将排序结果放在不同的数组中。我看见这个线程我在其中尝试了以下命令,尽管我修改了它,因为数组是变量而不是文件。

new_array=( $(ls -t $(printf '%s\n' "${array_list[@]}")) )

但是,数组太大,以至于 ls 报告参数列表“太长”

是否有另一种方法可以按修改日期对主数组进行排序,从最旧的文件开始,并将结果保存到不同的数组?

答案1

使用较新版本的 GNUlsbash,您可以执行以下操作:

readarray -td '' new_array < <(
  ls --zero -dt -- "${array_list[@]}")

但这并没有绕过execve()参数+环境长度的限制,因为我们ls使用该参数列表执行。您可以将该列表传递给printf不执行的函数或内置函数,execve()以将其输入到可以从 stdin 读取列表而不是作为参数的命令中。

对于最新版本的 GNU find (以及 GNUsortcut):

print0() { [ "$#" -eq 0 ] || printf '%s\0' "$@"; }
readarray -td '' new_array < <(
  print0 "${array_list[@]}" |
    find -files0-from - -prune -printf '%T@\t%p\0' |
      sort -rzn |
      cut -zf2 -)

或者使用 GNUstat并假设没有任何数组元素-

print0() { [ "$#" -eq 0 ] || printf '%s\0' "$@"; }
readarray -td '' new_array < <(
  print0 "${array_list[@]}" |
    xargs -r0 stat --printf='%.Y\t%n\0' --
      sort -rzn |
      cut -zf2 -)

zsh有一个stat内置的(早于 GNU 的)。因此,您可以直接在那里执行以下操作:

zmodload zsh/stat
typeset -A mtime
stat -nLA mtime -F %s%9. +mtime -- $array_list
new_array=( /(Ne['reply=($array_list)']nOe['REPLY=$mtime[$REPLY]']) )

这里构建一个关联数组以将文件映射到其生成时间,并使用glob 限定符 with (对于数字)对$mtime A列表进行排序。Oen

答案2

用一个一条内衬和readarray

readarray -td '' new_array < <( 
    perl -l0e '
        print join "\0",
        sort { -M $a <=> -M $b }
        grep -f, @ARGV
    '  -- "${array_list[@]}"
)

致谢斯蒂芬·查泽拉斯为了readarray

相关内容