「date -d @xxxxxx」と「find ./」コマンドをリンクする方法は?

「date -d @xxxxxx」と「find ./」コマンドをリンクする方法は?

1970年1月1日以降、名前がミリ秒単位のタイムスタンプであるいくつかのディレクトリがあります。

1439715011728
1439793321429
1439879712214
.
.

次の出力が必要です。

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
.
.

次のコマンドを使用すると、すべてのディレクトリを一覧表示できます。

find ./ -type d | cut -c 3-12

ただし、出力を次のコマンドに入れることはできず、date -d @xxxxxx出力を操作することもできません。

どうすればいいですか?

答え1

正しい方向に進んでいます(より簡単な解決策を見つけるには、2〜3つのコマンドを実行してください。以下を参照)。現在のディレクトリを削除する*のではなく、ミリ秒をやや単純化する1を使用してから、./結果をGNUparallelまたはxargs2にパイプする必要があります。

find * -type d | cut -c 1-10 | parallel date --date=@{} +%c

得るために

Sat 12 Sep 2015 08:35:11 CEST
Sun 13 Sep 2015 10:50:11 CEST
Mon 14 Sep 2015 08:35:21 CEST

あなたの例のように、その前に秒オフセットを追加します。

find * -type d | cut -c 1-10 | parallel 'echo "{} "  $(date --date=@{} +%c)'

または:

find * -type d | cut -c 1-10 | xargs -I{} bash -c 'echo "{} "  $(date --date=@{} +%c)'

取得するには:

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

しかし、これを行う方が簡単です。

find * -type d -printf "@%.10f\n" | date -f - +'%s  %c'

これにより、同じ要求出力が再提供されます。

使用の欠点は、拡張がコマンド*ラインによって制限されることですが、タイムスタンプ値に基づいてディレクトリを並べ替えることができるという利点があります。ディレクトリ数が問題の場合はこれを使用してください-mindepth 1。しかし、順序は失われます。

find ./ -mindepth 1 -type d -printf "@%.10f\n" | date -f - +'%s  %c'

sort必要に応じて挿入してください。

find ./ -mindepth 1 -type d -printf "@%.10f\n" | sort | date -f - +'%s  %c'

1これは、あなたの例のように入れ子になったサブディレクトリがないと仮定します。./ -mindepth 1*@hobbsと@don_crisstiが提案したように、ここで実行できる²の代わりに
²を使用することもできます。これはより冗長です。³sファイル読み取り機能の使用に対するGillesの回答に基づいて いますparallelxargs -I{}date

答え2

ループ内の各ファイルに対して複数のコマンドを実行しないようにします。すでにGNUismsを使用しているので:

find . ! -name . -prune -type d |
  awk '{t = substr($0, 3, 10); print t, strftime("%a %b %d %T %Z %Y", t)}'

2つのコマンドのみを実行します。strftime()GNU専用です。例: date -d

答え3

あなたはすでに持っています:

find ./ -type d | cut -c 3-12

これはおそらくエポック形式のタイムスタンプを提供します。ここでwhileループを追加してください。

find ./ -type d | cut -c 3-12 | while read datestamp
do
    printf %s "$datestamp"
    date -d "@$datestamp"
done

ただし、一部のシェルでは、この構文はサブシェルからwhileループを取得します。つまり、そこに変数を設定しようとすると、ループを離れると変数は表示されません。この問題を解決するには、状況を少し変更する必要があります。

while read datestamp
do
    printf %s "$datestamp"
    date -d "@$datestamp"
done < <(find ./ -type d | cut -c 3-12)

サブシェルに配置され、findメインシェルにwhileループを保持します。ただし、この構文(AT&Tkshと特定の構文)は、ループ内で結果を再利用したい場合にのみ必要です。zshbash

答え4

私がやるべきこと - タイムスタンプのリストを入力してください。

#!/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

この出力は次のようになります。

1442039711 Sat Sep 12 07:35:11 2015
1442134211 Sun Sep 13 09:50:11 2015
1442212521 Mon Sep 14 07:35:21 2015

特定の出力形式が必要な場合は、strftime次のように使用できます。

print $t->epoch, " ", $t->strftime("%Y-%m-%d %H:%M:%S"),"\n";

パイプのライナーに交換してください。

 perl -MTime::Piece -nle '$t=Time::Piece->new($_); print $t->epoch, "  ", $t, "\n";'

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, "." ); 

関連情報