使用 Bash 在文件夹子树的每个级别查找“最新”路径、文件名、日期和时间

使用 Bash 在文件夹子树的每个级别查找“最新”路径、文件名、日期和时间

使用 Bash,我想查找任何指定目录及其子树的文件名、最后在该目录中创建的文件的创建日期和创建时间。例如,输出将是:

/home/dir    filename0  creation_date0 creation_time0
/home/dir/subdir1    filename1  creation_date1  creation_time1
/home/dir/subdir2    filename2  creation_date2  creation_time2

答案1

尝试:

$ find /path/to/dir -type d -print0 | xargs -0 -I{} bash -c '
    path="{}";
    ls -oAF --time=ctime --time-style=+"%Y-%m-%d %H:%M:%S" -t "$path" | \
    awk -v dir="$path" '\''BEGIN {found=0} ($1 ~ /-[rwx-]{9}/ && found == 0) {printf "%s\t%s\t%s\t%s\n", dir, $7, $5, $6; found=1}'\'';'

使用制表符分隔的“absolute_path”、“filename”、“last_modif_date”、“last_modif_time”的示例输出:

/path/to/dir/otp_src_19.1/lib/ic/src    icparse.erl     2016-09-20        21:56:21
/path/to/dir/otp_src_19.1/lib/dialyzer  AUTHORS 2016-09-20        21:11:23
/path/to/dir/otp_src_19.1/lib/dialyzer/doc      about.txt       2016-09-20     21:11:23

2 条评论:

  • 上述解决方案基于最新的文件状态修改日期/时间,而不是基于最新的“出生”或“创建”日期/时间。要根据文件的创建日期/时间区分文件,您需要(扩展属性)在您的系统上启用。我假设您不这样做,因为它不是标准问题(POSIX),因此依赖此类元数据可能会导致可移植性问题。
    如果您确实已xattr启用,请编辑 OP 以使其清楚(并通知我),以便我可以更新此解决方案。
  • 使用zshshell 提出的解决方案可能比使用 更简单bash。仅在bashzsh与 with不同ls *(.))列表中常规文件withls是不可能的,即没有这样的标志或选项或特殊的通配模式来执行以下操作:ls --regular-file-only。因此,列出带有 的文件ls [options]将产生常规文件、链接和目录,以及$PWD.需要从中过滤掉常规文件。

怎么运行的:

  • find /path/to/dir -type d -print0查找从 开始的目录子树中的所有目录/path/to/dir。它打印每个目录,用 NULL 替换标准行尾字符,以避免目录名称中出现空格问题。这是通过管道输送到:
  • xargs -0 -I{} bash -c '...'从标准输入读取传入结果(这里标准输入被管道输入数据替换)并将它们呈现给以下迷你 Bash 脚本:
    • ls -oAF --time=ctime --time-style=+"%Y-%m-%d %H:%M:%S" -t "$path" |-AF以长格式列出“几乎所有”( ) 文件,不带组 ( -o) 信息,也不考虑传递目录中的文件类型$path,同时:
      • 格式化列出的文件输出 ( ),以便在下一步中可以轻松解析--time-style=+"%Y-%m-%d %H:%M:%S"其上次目录状态修改日期/时间 ( )。--time=ctime请注意,文件的目录状态修改时间可能与该文件自身的修改时间不同。
      • 根据文件显示的修改时间 ( -t) 对文件进行排序,最新的位于最前面。
      • 将格式化和排序的输出传输到以下awk过滤器中:
    • awk -v dir="$path" '...'
      • 将 的值赋给$path内部awk变量 dir
      • BEGIN {found=0}在块中将display-flag 设置found为 0BEGIN
      • ($1 ~ /-[rwx-]{9}/ && found == 0)对于每条记录,测试该文件是否是常规文件,在这种情况下,记录的第一个字段 ( $1) 应符合正则表达式-[rwx-]{9},以及 ( &&) 对于给定目录 ( ),这种情况是否至少发生过一次,$path在这种情况下,显示-flag ( found) 不再为零,并且跳过记录且不采取任何操作。
      • {printf "%s\t%s\t%s\t%s\n", dir, $7, $5, $6; found=1}只要不跳过记录,即该文件是常规文件并且是$path当前正在处理的目录( ) 中第一个显示的文件,该块就会执行。然后将显示标志 ( ) 设置为 1,以便不显示found同一目录 ( ) 中的其他文件。$path

find当你的目录树不小时,代码本质上依赖于主机,并且运行成本相当大。

相关内容