কীভাবে 'ডেট-ডি @ এমএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্সএক্স' এবং 'সন্ধান করুন ./'?


14

আমার ডিরেক্টরি রয়েছে যার নাম টাইমস্ট্যাম্পগুলি, 1970-01-01 থেকে মিলি সেকেন্ডে দেওয়া:

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
সেই টাইমস্ট্যাম্পগুলি কীভাবে পর্বতে অনুবাদ করবে? কারণ আপনার সংখ্যাগুলি অনেক দীর্ঘ ... (এটি প্রথমটি - এটি Fri Oct 2 05:35:28 47592)
সোব্রিক

1
@ সোব্রিক স্পষ্টতই মহাকাশকাল থেকে মিলি সেকেন্ডে।
গিলস 'অশুভ হওয়া বন্ধ করুন'

উত্তর:


10

আপনি সঠিক পথে আছেন (একটি সহজ সমাধানের জন্য, কেবল 2 বা 3 টি কমান্ড চলছে, নীচে দেখুন)। আপনার বর্তমান ডিরেক্টরিটি থেকে মুক্তি পাওয়ার *পরিবর্তে ব্যবহার করা উচিত- ./এবং এটি মিলিসেকেন্ডগুলি কিছুটা কাটাকে সহজতর করে, তারপরে ফলাফলটি কেবল জিএনইউ parallelবা pipe এ নল করুন 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প্রয়োজন হলে sertোকান:

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

¹ এটি ধরে নেয় কোনও নেস্টেড সাব-ডাইরেক্টরি নেই, যেমনটি আপনার উদাহরণ থেকে দেখা যায়। এছাড়াও আপনি ব্যবহার করতে পারেন ./ -mindepth 1পরিবর্তে*
² এর আপনি প্রতিস্থাপন করতে পারেন parallelসঙ্গে xargs -I{}এটা ঠিক অধিক বাগাড়ম্বরপূর্ণ @hobbs যেমন এখানে এবং @don_crissti প্রস্তাব। File ফাইল পড়ার ক্ষমতা ব্যবহার করার জন্য গিলসের জবাবের ভিত্তিতেdate


অথবা xargsযদি আপনার না থাকে parallel, যা সম্ভবত অনেকেই না করেন।
hobbs

@hobbs আমি যতদূর জানি xargsযেখানে যুক্তি যায় মত নির্দিষ্ট করার বিকল্প নেই parallelসঙ্গে হয়েছে {}
অ্যান্থন

4
এটি করে:find ./ -type d | cut -c 3-12 | xargs -I{} date --d @{} +'%Y-%m-%d'
don_crissti

@ আপনি যদি -Iবিকল্পটি ব্যবহার করেন তবে এটি কাজ করে ।
hobbs

1
অ্যানটন, জিএনইউ দীর্ঘ বিকল্পগুলি সংক্ষিপ্ত আকারে সংক্ষিপ্ত করা যেতে পারে যতক্ষণ না তারা অস্পষ্ট নয়। --dবা --daGNU এর বর্তমান সংস্করণগুলির সাথে কাজ করবে dateতবে এটি কাজ করা বন্ধ করতে পারে dateএকটি --dalekবিকল্প (ডালেক ক্যালেন্ডারের তারিখের জন্য) প্রবর্তন করে ।
স্টাফেন চেজেলাস

10

আমি প্রতি লুপটিতে কয়েকটি কমান্ড চালানো এড়াতে চাই। যেহেতু আপনি ইতিমধ্যে জিএনইউজম ব্যবহার করছেন:

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

যা কেবল দুটি কমান্ড চালায়। strftime()GNU- নির্দিষ্ট, মত date -d


এটি ডিরেক্টরি নামের মিলিসেকেন্ডগুলি কেটে দেয় না তবে অনুরোধ করা প্রথম 10 এর পরিবর্তে সম্পূর্ণ 13 টি অক্ষর প্রদর্শন করবে
অ্যান্থন

@ অ্যানহান, আহ হ্যাঁ, এই প্রয়োজনীয়তাটি মিস করল। এখনই ঠিক আছে।
স্টাফেন চেজেলাস

8

যদি আপনি ইতিমধ্যেই আছে:

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

যা সম্ভবত আপনাকে যুগের ফর্ম্যাটে টাইমস্ট্যাম্পগুলি দেয়। এবার কিছুক্ষণ লুপ যুক্ত করুন:

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

যদিও লক্ষ্য করুন যে কয়েকটি শেলের মধ্যে, সেই বাক্য গঠনটি একটি সাবশেলে কিছুক্ষণ লুপ পায়, যার অর্থ আপনি যদি সেখানে কোনও ভেরিয়েবল সেট করার চেষ্টা করেন, আপনি লুপটি ছেড়ে যাওয়ার পরে এটি দৃশ্যমান হবে না। এটি ঠিক করার জন্য, আপনাকে কিছুটা তাদের মাথার দিকে চালানো দরকার:

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

যা findসাবসেলের মধ্যে রাখে এবং মূল শেলের মধ্যে লুপটি রাখে। যে বাক্য গঠন (যেমন AT & T ksh, zshএবং bashআপনি, লুপ ভিতর থেকে ফলে পুনরায় ব্যবহার করার জন্য যদিও খুঁজছেন যদি নির্দিষ্ট) শুধুমাত্র প্রয়োজন হয়।


নির্বিশেষে, এটি যে বাশ-নির্দিষ্ট তা সঠিক নয় :)
ওয়াউটার ভারহেলস্ট

প্রকৃতপক্ষে, আপনি প্রথমদিকে যেমন লিখেছিলেন, done <(find)পরিবর্তে done < <(find), এটির জন্য সঠিক ছিল yash(যেখানে <(...)প্রক্রিয়া পুনর্নির্দেশটি হয়, বিকল্প প্রতিস্থাপন নয়), সুতরাং আমার সম্পাদনাটি কিছুটা অশ্বারোহী ছিল কারণ এটি আপনাকে বোঝানো শেল হতে পারে।
স্টাফেন চেজেলাস

6

আপনার যদি জিএনইউ তারিখ থাকে তবে এটি কোনও ইনপুট ফাইল থেকে পঠিত তারিখগুলিকে রূপান্তর করতে পারে। আপনাকে কেবল টাইমস্ট্যাম্পগুলিকে কিছুটা ম্যাসেজ করতে হবে যাতে এটি সেগুলি সনাক্ত করতে পারে। ইউনিক্স যুগের উপর ভিত্তি করে টাইমস্ট্যাম্পের জন্য ইনপুট সিনট্যাক্সটি @সেকেন্ডের সংখ্যার পরে আসে, যার দশমিক পয়েন্ট থাকতে পারে।

find ./ -type d ! -name '*[!0-9]*' |
sed -e 's~.*/~@~' -e 's~[0-9][0-9][0-9]$~.&~' |
date -f - +'%s  %c'

dateএস ফাইল পড়ার জন্য +1 । এটি date: invalid date ‘@’বর্তমান ডিরেক্টরি ( ./) এর অনুবাদ করার কারণে একটি কারণ দেয় । এবং যেহেতু আপনি মিলিসেকেন্ডগুলি ফেলে দিতে পারেন আপনি sedশেষ 3 অক্ষরটি সরাতে দ্বিতীয় সম্পাদনাটি সহজ করতে পারবেন । বা এগুলি সমস্ত অপসারণ করুন এবং ব্যবহার করুনfind * -type d -printf "@%.10f" | date ...
অ্যান্থন

5

আমি এটি মারাত্মকভাবে করব - টাইমস্ট্যাম্পগুলির তালিকায় ফিড দিন:

#!/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মডিউলটি ব্যবহার করে তার পরিবর্তে পার্লে পুরো জিনিসটি করার পরামর্শ দিই । আপনি যদি আপনার ডিরেক্টরি কাঠামোর কাটার আগে উদাহরণ দেন তবে আমি আপনাকে একটি উদাহরণ দেব। তবে এটি এমন কিছু হবে:

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

2

সাথে zshএবং স্ট্রফটাইম অন্তর্নির্মিত:

zmodload zsh/datetime
for d (*(/))
strftime '%s %a %b %d %T %Z %Y' $d

এটি ধরে নিয়েছে যে বর্তমান ডিরেক্টরিতে আপনার সমস্ত ডিরেক্টরি নাম আসলে যুগের সময় times
আপনার ফিল্টারিং / প্রক্রিয়াকরণ সম্ভব যখন আপনি উদাহরণস্বরূপ সেই সংখ্যাগুলি কীভাবে প্রক্রিয়াকরণ করা উচিত তা স্পষ্ট করে দেওয়া হয় (তারা প্রিন্সেস লিয়া এবং লুক স্কাইওয়াকারের জন্ম তারিখের সাথে আগের যুগের মতো দেখতে আরও বেশি ...) উদাহরণস্বরূপ কমপক্ষে মেলে এমন ডিরেক্টরিগুলির নাম অনুসন্ধান করুন। 10 টি সংখ্যা এবং প্রথম 10 সংখ্যার ভিত্তিতে তারিখ গণনা করুন:

setopt extendedglob
zmodload zsh/datetime
for d (**/[0-9](#c10,)(/))
strftime '%s %a %b %d %T %Z %Y' ${${d:t}:0:10}

2

জিএনইউ সমান্তরাল ব্যবহার:

find ./ -type d | cut -c 3-12 | parallel -k 'echo {} `date -d @{}`'

আপনি যদি স্থানটির পরিবর্তে accept t গ্রহণ করতে পারেন:

find ./ -type d | cut -c 3-12 | parallel -k --tag date -d @{}

parallelলিখিত আছে নোট perlperlএটি একটি strftime()অপারেটর আছে বিবেচনা করে ওভারকিল বলে মনে হচ্ছে । লাইকperl -MPOSIX -lpe '$_.=strftime(" %c", localtime substr $_, 2, 10)'
স্টাফেন চেজেলাস

2
1. এটি সংক্ষিপ্ত। ২. আপনার পার্ল শেখার দরকার নেই।
ওলে টাঞ্জ

1
এটি ২%% খাটো, তবে এটি বেশ দক্ষতার কম কয়েকটি অর্ডার (আমার যে পরীক্ষায় করা হয়েছে তার তুলনায় প্রায় 800 গুন; এটি শেল (আপনার শেল, / বিন / শ নয়) এবং প্রতিটি লাইনের জন্য একটি তারিখ কমান্ড উত্সাহিত করা প্রয়োজন বিবেচনা করুন) এবং সিস্টেমে বন্ধুত্বপূর্ণ হয়ে পড়ায় এটি একবারে সমস্ত সিপিইউ বোঝা করে। এবং আপনার এখনও শিখতে হবে parallel। আইএমও, parallelসিপিইউ নিবিড় কাজগুলিকে সমান্তরাল করার একটি দুর্দান্ত সরঞ্জাম, তবে এখানে এই ধরণের কাজের জন্য সত্যই উপযুক্ত নয়।
স্টাফেন চেজেলাস

এমন অনেকগুলি প্রসঙ্গ রয়েছে যেখানে দক্ষতা কোনও উদ্বেগ নয়, তাই এটি এখনও একটি গ্রহণযোগ্য সমাধান, তবে এটি এখনও পারফরম্যান্স ইস্যুটি উল্লেখ করার মতো, বিশেষত যখন সেই সমান্তরালটি সাধারণত লোকের মনে উচ্চ কার্যকারিতা সহ ছড়াগুলি বিবেচনা করে ।
স্টাফেন চেজেলাস

0

সাধারণত ফাইন্ড কমান্ডটি কোনও কমান্ড ব্যবহার করে শৃঙ্খলাবদ্ধ হতে পারে exec যুক্তির পারে।

আপনার ক্ষেত্রে, আপনি এটি করতে পারেন:

find . -type d | cut -c 3-12 | while read line
do
       echo -n "${line}  "
       date -d $line
done

0

পাইথন ব্যবহার করা (এটি সম্ভবত সবচেয়ে ধীর সমাধান)

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

অজগর এ সব না কেন? বরং একগুচ্ছ পাইপের শৃঙ্খলা?
সোবারিক

এটি আরও ভাল ধারণা করতে পারে। আমি রাজী.
lukaz
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.