【问题标题】:Linux - Finding the max modified date of each set of files in each directoryLinux - 查找每个目录中每组文件的最大修改日期
【发布时间】:2021-12-27 17:07:17
【问题描述】:

path/mydir 包含目录列表。这些目录的名称告诉我它们与哪个数据库相关。

每个目录里面都有一堆文件,但是文件名告诉我什么都不重要。

我正在尝试在 linux bash 中编写一个完成以下任务的命令:

  • 对于path/mydir 中的每个目录,查找该目录中最后修改文件的最大时间戳
  • 在父目录名称旁边打印上次修改文件的时间戳
  • 排除任何小于 30 天的时间戳
  • 使用正则表达式排除特定目录名称
  • 按最早的时间戳排序

鉴于path/mydir中的这个目录结构:

database_1
   table_1.file (last modified 2021-11-01)
   table_2.file (last modified 2021-11-01)
   table_3.file (last modified 2021-11-05)
database_2
   table_1.file (last modified 2021-05-01)
   table_2.file (last modified 2021-05-01)
   table_3.file (last modified 2021-08-01)
database_3
   table_1.file (last modified 2020-01-01)
   table_2.file (last modified 2020-01-01)
   table_3.file (last modified 2020-06-01)

我想输出:

database_3 2020-06-01
database_2 2021-08-01

这一半有效,但查看的是父目录的修改日期,而不是目录下文件的最大时间戳: find . -maxdepth 1 -mtime +30 -type d -ls | grep -vE 'name1|name2'

我是 bash 的新手,非常感谢任何帮助和指导!

【问题讨论】:

    标签: bash shell file timestamp filemtime


    【解决方案1】:

    请尝试以下方法

    #!/bin/bash
    
    cd "path/mydir/"
    for d in */; do
        dirname=${d%/}
        mdate=$(find "$d" -maxdepth 1 -type f -mtime +30 -printf "%TY-%Tm-%Td\t%TT\t%p\n" | sort -rk1,2 | head -n 1 | cut -f1)
        [[ -n $mdate ]] && echo -e "$mdate\t$dirname"
    done | sort -k1,1 | sed -E $'s/^([^\t]+)\t(.+)/\\2 \\1/'
    

    使用提供的示例输出:

    database_3 2020-06-01
    database_2 2021-08-01
    
    • for d in */; do 循环遍历 path/mydir/ 中的子目录。
    • dirname=${d%/} 删除尾部斜线只是为了打印。
    • printf "%TY-%Tm-%Td\t%TT\t%p\n" 前置修改日期和时间 到由制表符分隔的文件名。结果将如下所示:
    2021-08-01      12:34:56        database_2/table_3.file
    
    • sort -rk1,2 按日期和时间字段降序对输出进行排序。
    • head -n 1 选择具有最新时间戳的行。
    • cut -f1 提取具有修改日期的第一个字段。
    • [[ -n $mdate ]] 跳过空的mdate
    • sort -k1,1done 执行全局排序之后 子目录的输出。
    • sed -E ... 交换时间戳和目录名。它只是考虑 目录名可能包含制表符的情况。如果没有,你可以 通过切换时间戳和目录名的顺序省略sed 命令 在echo 命令中并将sort 命令更改为sort -k2,2

    至于提到的Exclude specific directory names using regex,添加 find 命令或其他任何东西的逻辑。

    [编辑]
    如果子目录中最后修改的文件早于指定日期,为了打印目录名称,请尝试:

    #!/bin/bash
    
    cd "path/mydir/"
    now=$(date +%s)
    for d in */; do
        dirname=${d%/}
        read -r secs mdate < <(find "$d" -type f -printf "%T@\t%TY-%Tm-%Td\n" | sort -nrk1,1 | head -n 1)
        secs=${secs%.*}
        if (( secs < now - 3600 * 24 * 30 )); then
            echo -e "$secs\t$dirname $mdate"
        fi
    done | sort -nk1,1 | cut -f2-
    
    • now=$(date +%s) 将变量 now 分配给当前时间为 自纪元以来的秒数。
    • for d in */; do 循环遍历 path/mydir/ 中的子目录。
    • dirname=${d%/} 删除尾部斜线只是为了打印。
    • -printf "%T@\t%TY-%Tm-%Td\n" 将修改时间打印为自以来的秒数 由制表符分隔的纪元和修改日期。 结果将如下所示:
    1627743600      2021-08-01
    
    • sort -nrk1,1 按修改时间降序对输出进行排序。
    • head -n 1 选择具有最新时间戳的行。
    • read -r secs mdate &lt; &lt;( stuff )secsmdate 分配给 命令的输出顺序。
    • secs=${secs%.*} 删除小数部分。
    • 条件(( secs &lt; now - 3600 * 24 * 30 ))满足如果secsnow 早 30 天或更长时间。
    • echo -e "$secs\t$dirname $mdate" 打印 dirnamemdate 为排序目的添加 secs
    • sort -nk1,1done 执行全局排序之后 子目录的输出。
    • cut -f2- 删除 secs 部分。

    【讨论】:

    • 这是一个很好的回应!这不仅可以正常工作,而且您在准确解释 bash 脚本的作用方面做得很好——我真的很感激。我如何修改它以查看最大修改日期的任何子目录中的文件?例如,如果path/mydir/database_3 包含额外的子目录而不仅仅是文件?假设我们有 table_1.file、table_2.file、table_3.file、folder_1->table_4.file、folder_2->table5.file?
    • 感谢您的反馈。很高兴知道它有效。至于您的其他情况,假设table5.file 具有最大修改日期,您要打印哪个目录名称,database_3folder_2
    • 仍然是 database_3。应查看 database_3 下的所有文件和子目录。如果最近修改的文件在 30 天或更长时间内没有被修改,则返回父目录以及该文件的时间戳
    • 明白。然后请删除find 命令的-maxdepth 1。它会按您的预期工作。
    • 完美运行,谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 2019-12-26
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    相关资源
    最近更新 更多