我有名称为时间戳的目录,自 1970-01-01 以来以毫秒为单位:
1439715011728
1439793321429
1439879712214
.
.
Run Code Online (Sandbox Code Playgroud)
我需要一个输出,如:
1442039711 Sat Sep 12 08:35:11 CEST 2015
1442134211 Sun Sep 13 10:50:11 CEST 2015
1442212521 Mon Sep 14 08:35:21 CEST 2015
.
.
Run Code Online (Sandbox Code Playgroud)
我可以通过命令列出所有目录:
find ./ -type d | cut -c 3-12
Run Code Online (Sandbox Code Playgroud)
但是我不能将输出放到下一个命令:date -d @xxxxxx并操作输出。
我怎样才能做到这一点?
Ant*_*hon 10
您走在正确的轨道上(对于更简单的解决方案,仅运行 2 或 3 个命令,请参见下文)。您应该使用*而不是./摆脱当前目录¹ ,这在某种程度上简化了毫秒的切割,然后只需将结果通过管道传输到 GNUparallel或xargs²:
find * -type d | cut -c 1-10 | parallel date --date=@{} +%c
Run Code Online (Sandbox Code Playgroud)
要得到
Sat 12 Sep 2015 08:35:11 CEST
Sun 13 Sep 2015 10:50:11 CEST
Mon 14 Sep 2015 08:35:21 CEST
Run Code Online (Sandbox Code Playgroud)
并在此之前添加秒偏移量,如您的示例所示:
find * -type d | cut -c 1-10 | parallel 'echo "{} " $(date --date=@{} +%c)'
Run Code Online (Sandbox Code Playgroud)
或者:
find * -type d | cut -c 1-10 | xargs -I{} bash -c 'echo "{} " $(date --date=@{} +%c)'
Run Code Online (Sandbox Code Playgroud)
要得到:
1442039711 Sat 12 Sep 2015 08:35:11 CEST
1442134211 Sun 13 Sep 2015 10:50:11 CEST
1442212521 Mon 14 Sep 2015 08:35:21 CEST
Run Code Online (Sandbox Code Playgroud)
然而,这样做更简单³:
find * -type d -printf "@%.10f\n" | date -f - +'%s %c'
Run Code Online (Sandbox Code Playgroud)
这再次为您提供相同的请求输出。
使用的缺点*是您受到命令行扩展的限制,但是优点是您可以按时间戳值对目录进行排序。如果目录数量有问题,请使用-mindepth 1,但会丢失排序:
find ./ -mindepth 1 -type d -printf "@%.10f\n" | date -f - +'%s %c'
Run Code Online (Sandbox Code Playgroud)
并sort在需要时插入:
find ./ -mindepth 1 -type d -printf "@%.10f\n" | sort | date -f - +'%s %c'
Run Code Online (Sandbox Code Playgroud)
¹这假设没有嵌套的子目录,就像您的示例中的情况一样。您也可以使用./ -mindepth 1代替*
²您可以像@hobbs 和@don_crissti 建议的那样parallel使用xargs -I{}此处替换,它只是更冗长。
³基于 Gilles 对使用date文件读取功能的回答
Sté*_*las 10
我会避免在循环中为每个文件运行多个命令。由于您已经在使用 GNUism:
find . ! -name . -prune -type d |
awk '{t = substr($0, 3, 10); print t, strftime("%a %b %d %T %Z %Y", t)}'
Run Code Online (Sandbox Code Playgroud)
它只运行两个命令。strftime()是特定于 GNU 的,例如date -d.
你已经有了:
find ./ -type d | cut -c 3-12
Run Code Online (Sandbox Code Playgroud)
这大概会为您提供纪元格式的时间戳。现在添加一个while循环:
find ./ -type d | cut -c 3-12 | while read datestamp
do
printf %s "$datestamp"
date -d "@$datestamp"
done
Run Code Online (Sandbox Code Playgroud)
请注意,在某些 shell 中,该语法在子 shell 中获取 while 循环,这意味着如果您尝试在那里设置变量,一旦离开循环,它将不可见。为了解决这个问题,你需要稍微改变一下他们的想法:
while read datestamp
do
printf %s "$datestamp"
date -d "@$datestamp"
done < <(find ./ -type d | cut -c 3-12)
Run Code Online (Sandbox Code Playgroud)
将 放在find子shell 中,并将while 循环保留在主shell 中。但是ksh,仅当您希望重用循环内部的结果时才需要该语法(AT&Tzsh和bash特定的)。
如果您有 GNU 日期,它可以转换从输入文件中读取的日期。您只需要稍微按摩时间戳,以便它可以识别它们。基于 Unix 纪元的时间戳的输入语法@后跟秒数,其中可以包含小数点。
find ./ -type d ! -name '*[!0-9]*' |
sed -e 's~.*/~@~' -e 's~[0-9][0-9][0-9]$~.&~' |
date -f - +'%s %c'
Run Code Online (Sandbox Code Playgroud)
我会做的很简单 - 输入时间戳列表:
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
while ( my $ts = <DATA> ) {
chomp ( $ts );
my $t = Time::Piece->new();
print $t->epoch, " ", $t,"\n";
}
__DATA__
1442039711
1442134211
1442212521
Run Code Online (Sandbox Code Playgroud)
这输出:
1442039711 Sat Sep 12 07:35:11 2015
1442134211 Sun Sep 13 09:50:11 2015
1442212521 Mon Sep 14 07:35:21 2015
Run Code Online (Sandbox Code Playgroud)
如果你想要一个特定的输出格式,你可以使用strftime例如:
print $t->epoch, " ", $t->strftime("%Y-%m-%d %H:%M:%S"),"\n";
Run Code Online (Sandbox Code Playgroud)
将其变成管道中的一个衬里:
perl -MTime::Piece -nle '$t=Time::Piece->new($_); print $t->epoch, " ", $t, "\n";'
Run Code Online (Sandbox Code Playgroud)
但我可能会建议改为查看使用File::Find模块并在 perl 中完成整个事情。如果你在剪切之前给出你的目录结构的例子,我会给你一个例子。但它会是这样的:
#!/usr/bin/env perl
use strict;
use warnings;
use Time::Piece;
use File::Find;
sub print_timestamp_if_dir {
#skip if 'current' item is not a directory.
next unless -d;
#extract timestamp (replicating your cut command - I think?)
my ( $timestamp ) = m/.{3}(\d{9})/; #like cut -c 3-12;
#parse date
my $t = Time::Piece->new($timestamp);
#print file full path, epoch time and formatted time;
print $File::Find::name, " ", $t->epoch, " ", $t->strftime("%Y-%m-%d %H:%M:%S"),"\n";
}
find ( \&print_timestamp_if_dir, "." );
Run Code Online (Sandbox Code Playgroud)