Bash
遞歸遍歷目錄並檢索最後一個時間戳文件
假設我有以下時間戳,如目錄樹:
root |__ parent1 | |__ 2021 | | |__ 01 | | | |__ 22 | | | | |__ 12H | | | | | |__ file1 | | | | | |__ file2 | | | | |__ 13H | | | | | |__ file1 | | | | | |__ file2 | | | |__ 23 | | | | |__ 12H | | | | | |__ file1 | | | | | |__ file2 | | | | |__ 13H | | | | | |__ file1 | | | | | |__ file2 |__ parent2 | |__ etc
我想要的是遞歸地瀏覽這個文件夾結構,這樣,對於每個文件夾
parent1
,parent2
等,將顯示找到的最新時間戳,以及包含的文件數。例如,類似:PARENT | LAST_TIMESTAMP | COUNT | -------------------------------------------- parent1 | 2021-01-23T13:00:00 | 2 | parent2 | 2022-01-01T00:00:00 | 5 | (dummy example) ... ... ...
我已經看到了其他答案,但所有答案都只考慮了所有文件夾中文件的修改日期,而在這種情況下,它只與文件夾的名稱有關。
使用
find
和perl
單線:這使用製表符來分隔時間戳和文件名,並使用 NUL 來分隔每條記錄 - 因此可以使用任何文件名,包括那些包含換行符的文件名。
find .. -type f -printf '%T@\t%p\0' | perl -MDate::Format -0ne ' ($t,$f) = split /\t/,$_,2; (undef,$p) = split "/", $f; $T{$p} = $t if ($t > $T{$p}); $count{$p}++; END { my $fmt = "%-20s | %-19s | %5s |\n"; printf "$fmt", "PARENT", "LAST_TIMESTAMP", "COUNT"; print "-" x 52, "\n"; foreach (sort keys %T) { printf $fmt, $_, time2str("%Y-%m-%dT%H:%M:%S",$T{$_}), $count{$_} } }'
它產生如下輸出:
PARENT | LAST_TIMESTAMP | COUNT | ---------------------|---------------------|-------| foo | 2021-07-16T22:54:22 | 4 | bar | 2021-06-29T12:25:06 | 13 | baz | 2021-07-14T14:31:43 | 5 | quux | 2021-07-16T19:46:21 | 7 |
或者,如果您使用 perl 的File::Find模組,則不需要將
find
’ 的輸出通過管道傳輸到其中:#!/usr/bin/perl use strict; use Date::Format; use File::Find; my %T; # hash containing newest timestamp for each top-level dir my %count; # count of files in each top-level dir find(\&wanted, @ARGV); my $fmt = "| %-20s | %-19s | %5s |\n"; my $hfmt = "|-%-20s-|-%-19s-|-%5s-|\n"; #print "-" x 54, "\n"; printf "$fmt", "PARENT", "LAST_TIMESTAMP", "COUNT"; printf $hfmt, "-" x 20, "-" x 19, "-" x 5; foreach (sort keys %T) { printf $fmt, $_, time2str("%Y-%m-%dT%H:%M:%S", $T{$_}), $count{$_} } #print "-" x 54, "\n"; sub wanted { return unless -f $File::Find::name; # uncomment only one of the following statements: # get the mod time of the file itself my $t = (stat($File::Find::name))[9]; # get the mod time of the directory it's in #my $t = (stat($File::Find::dir))[9]; my $p = $File::Find::dir; $p =~ s:^\.*/::; $T{$p} = $t if ($t > $T{$p}); $count{$p}++; };
將其另存為,例如
find-latest.pl
,make executable withchmod +x find-latest.pl
並在執行時給它一個或多個目錄作為參數:$ ./find-latest.pl ../ | PARENT | LAST_TIMESTAMP | COUNT | |----------------------|---------------------|-------| | foo | 2021-07-16T22:54:22 | 4 | | bar | 2021-06-29T12:25:06 | 13 | | baz | 2021-07-14T14:31:43 | 5 | | quux | 2021-07-16T19:46:21 | 7 |
這需要 perl Date::Format 模組。在 debian 上,您可以使用
apt-get install libtimedate-perl
. 它也應該為其他發行版打包,否則使用cpan
.或者,您可以使用
strftime()
POSIX 模組中的函式,它是一個核心模組,包含在 perl 中。
File::Find
也是 perl 的核心模組,包含在 perl 中。