I keep on getting errors on this routine for line 51 where i user the mkpath - I tried putting the File::Copy at the top of the subroutine ( line 38 )but still get error -
use warnings;
use DBI;
use File::Copy;
unshift #INC, "/production/lib";
require "config.pl";
$configFile = "/production/cfg/syncUsers.cfg";
readConfig($configFile);
doBackup($prefs{passwdFile});
# generatePasswdFile("tmpusers");
# getUsers($prefs{dbUser}, $prefs{dbPass}, $prefs{dbSid});
# copyPasswdFile($prefs{passwdFile});
# doBackup - backup the existing
sub doBackup {
#use File::Copy;
my (#theMonth, $month, $day, $year) = "";
if (!-e $prefs{passwdFile}) {
print "Password file: $prefs{passwdFile} does not exist. No backup being made.\n";
}
else {
print "$prefs{passwdFile} found. Performing backup.\n";
($mday, $mon, $year) = (localtime(time))[3 .. 5];
#theMonth = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
$month = $theMonth[$mon];
$day = sprintf("%02d", $mday);
$year = sprintf("%04d", $year + 1900);
$backupDir = "$prefs{backupDir}/$year$month$day/webstart";
print "$backupDir\n";
mkpath($backupDir); # Line 51
if (-e "$backupDir") {
move($prefs{passwdFile}, $backupDir);
}
else {
print "The backup directory was not created\n";
}
if (-e "$backupDir/etc-users") {
print "Backup successful. Generating file.\n";
}
else {
print "Backup failed. Exiting.\n";
exit 1;
}
}
}
and this is the result:
/production/web/users/etc-users1 found. Performing backup.
/production/archive/2013Nov19/webstart
Undefined subroutine &main::mkpath called at ./testbackup.pl.seco line 51.
the module is on the host:
bash-3.00$ perldoc -l File::Copy
/usr/local/perl5.8.8/lib/5.8.8/File/Copy.pm
bash-3.00$
File::Copy does not have mkpath, but
File::Path does.
Change:
use File::Copy;
to:
use File::Path;
Does File::Copy autoexport mkpath? Or maybe you need either
use File::Copy qw/ mkpath /;
or to call it as
File::Copy::mkpath()
Related
I'm creating a script where I need to get the Last Modified Date of the files
I checked this thread How do I get a file's last modified time in Perl?
So I used the script below to get the last modified, at first it was working but when I try to run it again, the timestamp returns 00:00 January 1, 1970.
Why is that happening and how can I get the correct last modified date and time?
my $dir = '/tmp';
opendir(DIR, $dir) or die $!;
#content=readdir(DIR);
foreach(#content)
{
next unless ($_ =~ m/\bfile.txt|file2.csv\b/);
my $epoch_timestamp = (stat($_))[9];
my $timestamp = localtime($epoch_timestamp);
$f_detail = $_ .' '.$timestamp;
print "$f_detail\n";
}
closedir(DIR);
exit 0;
When I tried to run the perl, I will get this result
file.txt Thu Jan 1 00:00:00 1970
file2.csv Thu Jan 1 00:00:00 1970
Ok, last update, it is working now, I try to run all of the scripts you've given to me, standalone script. I found what's causing the default time, see the script below, I remove that in my program and it works, didn't notice this at first, sorry. But still, it feels weird because I was sure that it is working when I first run it, but now it is working so yeah thank you guys!
if (($month = ((localtime)[4] + 1)) < 10)
{
$month = '0' . $month;
}
if (($day = ((localtime)[3])) < 10)
{
$day = '0' . $day;
}
if (($year = ((localtime)[5]+1900)) >= 2000)
{
if (($year = $year - 2000) < 10)
{
$year = '0' . $year;
}
}
else
{
$year = $year - 1900;
}
$date = $month . $day . $year;
readdir returns file names without the full path. You need to prepend the path manually:
for (#content) {
next unless /^(?:file\.txt|file2\.csv)\z/;
my $epoch_timestamp = (stat("$dir/$_"))[9];
# ~~~~~~~~~
Also note how I changed the regex to match the file names.
If you have a directory name, and you want to see if some files whose names you already know exist in that directory, there's really no need for opendir/readdir - that's more helpful if you don't know the filenames ahead of time. When you do, you can just build a path using both parts and use file test operators/stat/etc. on it.
#!/usr/bin/env perl
use strict;
use warnings;
use feature qw/say/;
my $dir = '/tmp';
my #files = qw/file.txt file2.csv/;
for my $file (#files) {
# Better to use File::Spec->catfile($dir, $file), but your question
# title said no modules...
my $name = "$dir/$file";
if (-e $name) { # Does the file exist?
# _ to re-use the results of the above file test operator's stat call
my $epoch_timestamp = (stat _)[9];
my $timestamp = localtime $epoch_timestamp;
say "$file $timestamp";
}
}
Example execution:
$ perl demo.pl
file.txt Tue Feb 8 07:26:07 2022
file2.csv Tue Feb 8 07:26:10 2022
Following demo code utilizes glob to obtain modification time for specified files in a directory.
use strict;
use warnings;
use feature 'say';
my $dir = '/tmp';
my #files = qw(file.txt file2.csv);
my $mask = join ' ', map { "$dir/$_" } #files;
say "$_\t" . localtime((stat($_))[9]) for glob($mask);
I'm trying to output "not ok" if the date provided within an input file is greater than one day from "today" using Perl version 5.8.8.
Initializing with "./code.sh < test.txt" works fine, when test.txt contains the following data:
07/02/2020 08/02/2020
When I rehash the code below to try an use "today's date" as a variable, and only have one date within the input file I get the following error:
Use of uninitialized value in concatenation (.) or string at code.sh line 27, <> line 1
Working code (with two dates in the input file):
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
#my $date = localtime->strftime('%d/%m/%Y');
#print "$date";
my $format = '%d/%m/%Y';
while (<>) {
chomp;
my ($str1, $str2) = split;
# my ($date, $str2) = split;
# my $dt1 = Time::Piece->strptime($date, $format);
my $dt1 = Time::Piece->strptime($str1, $format);
my $dt2 = Time::Piece->strptime($str2, $format);
# print "$date / $str2 ";
print "$str1 / $str2 ";
if ($dt2->julian_day - $dt1->julian_day ==1) {
print "ok\n";
} else {
print "not ok\n";
}
}
Broken code (with one date within the input file):
#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
my $date = localtime->strftime('%d/%m/%Y');
print "$date";
my $format = '%d/%m/%Y';
while (<>) {
chomp;
# my ($str1, $str2) = split;
my ($date, $str2) = split;
my $dt1 = Time::Piece->strptime($date, $format);
# my $dt1 = Time::Piece->strptime($str1, $format);
my $dt2 = Time::Piece->strptime($str2, $format);
print "$date / $str2 ";
# print "$str1 / $str2 ";
if ($dt2->julian_day - $dt1->julian_day ==1) {
print "ok\n";
} else {
print "not ok\n";
}
}
Not quite sure what I'm doing wrong...
Any help is appreciated
Please pay more attention when you type your code, your sample had a few miss-types
#!/usr/bin/perl
#
# vim: ai:ts=4:sw=4
#
use strict;
use warnings;
use feature 'say';
use Time::Piece;
my $format = '%d/%m/%Y';
my $date = localtime->strftime($format);
say "Today is: $date\n";
my #str_dates = <DATA>;
chomp(#str_dates);
my $date1 = Time::Piece->strptime($str_dates[0], $format);
my $date2 = Time::Piece->strptime($str_dates[1], $format);
my $days_diff = $date2->julian_day - $date1->julian_day;
my $msg = ($days_diff == 1) ? "ok" :"not ok";
say "$date2 :: $date1 => $msg";
say "$date2 :: $date1 = $days_diff day(s) apart";
__DATA__
07/02/2020
08/02/2020
Output
Today is: 07/02/2020
Sat Feb 8 00:00:00 2020 :: Fri Feb 7 00:00:00 2020 => ok
Sat Feb 8 00:00:00 2020 :: Fri Feb 7 00:00:00 2020 = 1 day(s) apart
NOTE: I would recommend if you use:
Windows OS
notepad++
Linux OS vim
vim better use with options: syntax on, ai,ts=4,sw=4
The below script will move the files having modification time older than three hours from /tmp/test1 folder to /data/ARCHIVE folder.
The issue is that if the ARCHIVE folder already has a file with same name as in the test1 folder it will overwrite them, which is unwanted.
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
use File::Copy;
my $dstdir = '/data/ARCHIVE/';
#ARGV = ("/tmp/test1") unless #ARGV;
print STDERR "Begin # ", scalar localtime, "\n";
find(
sub {
if ( -f $_ && -M _ >= 3 / 24 ) {
print STDERR "Moving '$_'\n";
move( $File::Find::name, $dstdir ) or die "$!\n";
}
},
#ARGV
);
print STDERR "Ended # ", scalar localtime, "\n";
1;
Add the epoch to the file name. But don't run your code more than once a second.
my $now = strftime( '%Y%m%d%H%M%S', localtime );
find(
sub {
if ( -f $_ && -M _ >= 3 / 24 ) {
print STDERR "Moving '$_'\n";
my $dst = "$dstdir/$_.$now";
move( $File::Find::name, $dst ) or die "$!\n";
}
},
#ARGV
);
I am having an issue with getting File::stat to output the last modified date of the file. This is my code so far:
#!/usr/bin/perl
use Time::localtime;
use File::stat;
use warnings;
use File::Find;
my $dirloc = 'E:\tmp\testdir';
sub find_txt {
my $F = $File::Find::name;
if ( ! -d $F && $F =~ /.tar|.exe|.zip/ ) {
my #result = $F;
foreach my $result (#result){
my $timestamp;
$timestamp = (stat("$result"))->[9] or die "No $_: $!";
print "$result : $timestamp\n";
}
}
}
find({wanted => \&find_txt}, $dirloc);
It is outputing something like this:
C:/tmp/testdir/foo/bar/test.tar : 1415305933
I need it to output instead (date format doesn't have to be what is listed, i just want to see the date):
C:/tmp/testdir/foo/bar/test.tar : 11/07/2014
I know that the output it is giving me is the time since epoch but I thought stat was supposed to give the date. Am I doing something wrong? Thanks!
edit: I have tried localtime, and i get: Time::tm=ARRAY(0x245b220), not sure what is happening there
You can use the localtime (Note: not Time::localtime) function to convert the timestamp into something useful
my $date = localtime $timestamp
which will make it a human readable string like Fri Nov 7 15:33:00 2014
Or you can use it in a list context to spit it into individual fields:
my($sec, $min, $hour, $day, $month, $year, $weekday, $yearOfDay, $isDST) = localtime $timestamp
I am attempting to write a Perl script that parses a log where on each line the second value is the date. The script takes in three arguments: the input log file, the start time, and the end time. The start and end time are used to parse out a certain value on each line that that falls between those two times. But to properly run this I am converting the start and end time to epoch time. The problem I am having is that to convert the loops 'i' value back to normal time to compare against the log file. After running localtime($i) I print the value and only see a reference printed not the actual value.
Here is the script I have so far (it is a work in progress):
#!/usr/bin/perl
use strict;
use warnings;
use Time::Local;
use Time::localtime;
use File::stat;
my $sec = 0;
my $min = 0;
my $hour = 0;
my $mday = 0;
my $mon = 0;
my $year = 0;
my $wday = 0;
my $yday = 0;
my $isdst = 0;
##########################
# Get the engine log date
##########################
my $date = `grep -m 1 'Metric' "$ARGV[0]" | awk '{print \$2}'`;
($year,$mon,$mday) = split('-', $date);
$mon--;
#########################################
# Calculate the start and end epoch time
#########################################
($hour,$min,$sec) = split(':', $ARGV[1]);
my $startTime = timelocal($sec,$min,$hour,$mday,$mon,$year);
($hour,$min,$sec) = split(':', $ARGV[2]);
my $endTime = timelocal($sec,$min,$hour,$mday,$mon,$year);
my $theTime = 0;
for (my $i = $startTime; $i <= $endTime + 29; $i++) {
#print "$startTime $i \n";
$theTime = localtime($i);
#my $DBInstance0 = `grep "$hour:$min:$sec" "$ARGV[0]"`;# | grep 'DBInstance-0' | awk '{print \$9}'`;
#print "$DBInstance0\n";
print "$theTime\n";
}
print "$startTime $endTime \n";
The output looks like:
Time::tm=ARRAY(0x8cbbd40)
Time::tm=ARRAY(0x8cbc1a0)
Time::tm=ARRAY(0x8cbbe80)
Time::tm=ARRAY(0x8cbc190)
Time::tm=ARRAY(0x8bbb170)
Time::tm=ARRAY(0x8cbc180)
Time::tm=ARRAY(0x8cbbf30)
Time::tm=ARRAY(0x8cbc170)
Time::tm=ARRAY(0x8cbc210)
Time::tm=ARRAY(0x8cbc160)
1275760356 1275760773
I only have access to the core Perl modules and am unable to install any others.
You can use ctime, depending on your definition of "Normal time":
Example code:
use Time::Local;
use Time::localtime;
my $time=timelocal(1,2,3,24,6,2010);
print "$time\n";
$theTime = ctime($time);
print "$theTime\n";
Result:
1279954921
Sat Jul 24 03:02:01 2010
Also, you don't need to use Time::Localtime (which is why you get Time::tm instead of a standard array/string from Perl's internal localtime):
use Time::Local;
my $time=timelocal(1,2,3,24,6,2010);
print "$time\n";
$theTime = localtime($time);
print "$theTime\n";
1279954921
Sat Jul 24 03:02:01 2010
Don't forget to subtract 1900 from the year!
Remember that in scalar context, localtime and gmtime returns a ctime-formatted string, so you could use it as in the following. If that's unsuitable, you might want to use strftime from the POSIX module.
#! /usr/bin/perl
use warnings;
use strict;
use Time::Local;
my $start = "01:02:03";
my $end = "01:02:05";
my $date = "2010-02-10";
my($year,$mon,$mday) = split /-/, $date;
$mon--;
$year -= 1900;
my($startTime,$endTime) =
map { my($hour,$min,$sec) = split /:/;
timelocal $sec,$min,$hour,$mday,$mon,$year }
$start, $end;
for (my $i = $startTime; $i <= $endTime + 29; $i++) {
print scalar localtime($i), "\n";
}
print "$startTime $endTime \n";
Tail of the output:
Wed Feb 10 01:02:26 2010
Wed Feb 10 01:02:27 2010
Wed Feb 10 01:02:28 2010
Wed Feb 10 01:02:29 2010
Wed Feb 10 01:02:30 2010
Wed Feb 10 01:02:31 2010
Wed Feb 10 01:02:32 2010
Wed Feb 10 01:02:33 2010
Wed Feb 10 01:02:34 2010
1265785323 1265785325