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
と出力を操作します。
これどうやってするの?
あなたは正しい軌道に乗っています(より簡単な解決策については、2つまたは3つのコマンドのみを実行します。以下を参照してください)。現在のディレクトリを削除するには、*
ではなく./
を使用する必要があります。これにより、ミリ秒の削減が多少簡単になり、結果をGNU parallel
またはxargs
²:
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'
¹ これは、例にあるように、ネストされたサブディレクトリがないことを前提としています。 ./ -mindepth 1
の代わりに*
を使用することもできます
²@hobbsと@don_crisstiが示唆しているように、ここでparallel
をxargs -I{}
に置き換えることができます。 ³date
sファイル読み取り機能を使用するためのGillesの回答に基づく
ループ内でファイルごとにいくつかのコマンドを実行することは避けます。あなたはすでにGNUismを使っているので:
_find . ! -name . -Prune -type d |
awk '{t = substr($0, 3, 10); print t, strftime("%a %b %d %T %Z %Y", t)}'
_
2つのコマンドを実行するだけです。 strftime()
は、_date -d
_のようにGNU固有です。
あなたはすでに持っています:
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&T ksh
、zsh
およびbash
固有)は、ループ内からの結果を再利用する場合にのみ必要です。
GNU日付がある場合は、入力ファイルから読み取った日付を変換できます。タイムスタンプを少しマッサージするだけで、それらを認識できます。タイムスタンプの入力構文は、 Unixエポックは@
の後に秒数が続きます。小数点を含めることができます。
find ./ -type d ! -name '*[!0-9]*' |
sed -e 's~.*/~@~' -e 's~[0-9][0-9][0-9]$~.&~' |
date -f - +'%s %c'
私はそれを徹底的に行います-タイムスタンプのリストをフィードします:
#!/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";
これをパイプの1つのライナーに変えるには:
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, "." );
zsh
および strftime 組み込み:
zmodload zsh/datetime
for d (*(/))
strftime '%s %a %b %d %T %Z %Y' $d
これは、現在のディレクトリ内のすべてのディレクトリ名が実際にはエポック時間であることを前提としています。
例のそれらの数値をどのように処理するかを明確にすれば、さらにフィルタリング/処理を行うことができます(レイア姫とルークスカイウォーカーの誕生日に対応するエポック時間に似ています...)。少なくとも10桁に一致するディレクトリ名を再帰的に検索し、最初の10桁に基づいて日付を計算します。
setopt extendedglob
zmodload zsh/datetime
for d (**/[0-9](#c10,)(/))
strftime '%s %a %b %d %T %Z %Y' ${${d:t}:0:10}
GNU Parallelを使用:
find ./ -type d | cut -c 3-12 | parallel -k 'echo {} `date -d @{}`'
スペースの代わりに\ tを受け入れることができる場合:
find ./ -type d | cut -c 3-12 | parallel -k --tag date -d @{}
Pythonを使用します(これはおそらく最も遅いソリューションです)
for i in $(ls -A); do echo $i | xargs python -c "from sys import argv;from time import strftime;from datetime import datetime;print datetime.fromtimestamp(float(argv[1][:-3])).strftime('%Y-%m-%d %H:%M:%S'),'---',argv[1]"; done
与える:
2015-08-30 08:48:59 --- 1440917339340
2015-08-31 08:00:22 --- 1441000822458
2015-09-01 08:00:32 --- 1441087232437
2015-09-01 16:48:43 --- 1441118923773
2015-09-02 08:00:11 --- 1441173611869
2015-09-03 08:00:32 --- 1441260032393
2015-09-04 08:00:21 --- 1441346421651
通常、findコマンドは、exec
引数を使用して任意のコマンドと連鎖させることができます。
あなたの場合、あなたはこのようにすることができます:
find . -type d | cut -c 3-12 | while read line
do
echo -n "${line} "
date -d $line
done