
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
またはxargs
2にパイプする必要があります。
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の回答に基づいて
いますparallel
xargs -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
と特定の構文)は、ループ内で結果を再利用したい場合にのみ必要です。zsh
bash
答え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, "." );