Get path relative to home directory in perl - perl

For this problem I found one solution, but I am looking for alternative solutions.
Assume I am in directory
/home/user/testA/testB
and my home directory is /home/user, how can I obtain the path of the current directory relative to my home directory? That is: testA/testB.
I tried the following:
use Cwd qw(getcwd);
use Env qw(HOME);
my $cdir=getcwd;
my $p=$cdir=~s{^\Q$HOME\E/}{}r;
and it seems to work. My question is if there is a CPAN module for doing this? The closest I came was File::Spec::Functions qw(abs2rel) but it just gives me ../.. .. maybe I missed something?

This seems to work fine to me with File::Spec
#!usr/bin/perl
use File::Spec;
$base = '/home/user';
$path = '/home/user/testA/testB';
my $rel_path = File::Spec->abs2rel( $path, $base );
print($rel_path);
Output:
testA/testB

Using Path::Tiny:
#!/usr/bin/perl
use warnings;
use strict;
use Path::Tiny;
my $base = '/home/user';
my $path = '/home/user/testA/testB';
my $relative = path($path)->relative($base);
print "$relative\n";

Related

get latest file from directory with pattern matching: Perl

I am newbie to perl and working on a script to find the files with pattern matching having latest modified timestamp and copy to another location.
my code is working on Mac, but having issues on windows server.
use strict;
use warnings;
use File::stat;
my $UNC ="/Users/documents/";
my $FileNamePrefix = "abc*.csv";
my #files = sort {stat($a)->mtime <=> stat($b)->mtime} glob($UNC.$FileNamePrefix);
my $Recon = $files[-1];
print "Latest = $Recon\n";
can someone please help me with this code, Thank you
Source location:
abc_20181.csv (yesterdaydate)
abc_20182.csv (todaysdate)
Target location:
abc_20182.csv
You could use File::Spec to create the paths, and it will create the correct syntax based on the OS it's running on. For example:
use strict;
use warnings;
use File::stat;
my $UNC ="/Users/documents/";
my $FileNamePrefix = "abc*.csv";
# platform specific path:
my $pattern = File::Spec->catpath('', $UNC, $FileNamePrefix);
my #files = sort {stat($a)->mtime <=> stat($b)->mtime} glob($pattern);
my $Recon = $files[-1];
print "Latest = $Recon\n";
This will make the pattern "/Users/documents/abc*.csv" on Mac and "\Users\documents\abc*.csv" on Windows.
See "perldoc File::Spec" for more examples.

How to include perl modules while started from other directory?

I am writing some perl script and I want to include module. Everything is okay when I am in the same directory that my script.pl is. But when I try to start my script from other directory it says it cant locate my module. My includes looks like this:
use Functions qw(translateWord sendHelp);
and the file with module is called Functions.. I tried something like this:
use lib '..';
but it failed too.. I also tried:
use Cwd 'abs_path';
BEGIN {
my $dir = abs_path($0);
use lib "$dir";
}
but again it failed.. I also tried this:
use Cwd 'abs_path';
my $dir = abs_path($0);
use lib $dir;
and still fail.. I am new to Perl.
Thanks in advance!
The canonical way of accomplishing this is with 'use lib'. Using a lib of .. is not ideal though, because it's relative to the current working directory when you invoke the script.
The way to accomplish this is with FindBin.
E.g.
use FindBin;
use lib $FindBin::Bin."/../";
To traverse up a directory level from the 'base location' of your script.
Try this :
BEGIN{
unshift #INC, '/FULL/PATH/TO/DIR/OF/YOUR/MODULE';
}

Perl -How do i pass complete directory path name into perl script

I have a perl script and its been executing from "/root/pkt/sw/se/tool" path and would need the complete directory path inside the script.
Can you please let me know how would i get the complete path?
sample.pl
our ($tool_dir);
use strict;
use warnings;
BEGIN {
$tool_dir = $0;
my $home_path = $tool_dir
$home_path =~ s|\w*/\w*/\w*$||;
my $target_path ="obj/Linux-i686/usr/share/ddlc/lib";
$lib_dir = "$home_path$target_path";
unshift(#INC, $lib_dir);
}
And i am executing this script from "pkt/sw/se/tool" path but here i am getting only "pkt/sw/se/tool" instead of "/root/pkt/sw/se/tool"
my perl script is available under /root/pkt/sw/se/tools/sample.pl
You can use the CWD module (http://perldoc.perl.org/Cwd.html) (code take from that page)
use Cwd;
my $dir = getcwd;
use Cwd 'abs_path';
my $abs_path = abs_path($file);
or you could execute the pwd command
$cwd = `pwd`;
If you just want the directory, not the full path, you could check out an existing answer at Print current directory using Perl
Use one of the modules already mentioned, never use backticks - unless you fully understand the risks and implications of doing so. If you do want to run 'pwd' then call it via something like IPC::Run3.
Examples:
#!/usr/bin/perl
use strict;
use warnings;
use Cwd;
use IPC::Run3;
# CWD
my $working_dir_cwd = getcwd;
print "Woring Dir (Cwd): $working_dir_cwd\n";
# IPC::Run3
my ($in, $out, $err);
my #command = qw/pwd/;
run3 \#command, $in, \$out, \$err or die $?;
print "Working Dir (pwd): $out\n";
You can use FindBin to locate directory of original perl script.
use FindBin;
use lib "$FindBin::Bin/../../../obj/Linux-i686/usr/share/ddlc/lib";

Print current directory using Perl

I have this code to print the current directory using Perl:
use Cwd qw(abs_path);
my $path = abs_path($0);
print "$path\n";
But it is displaying the filename of my script along with the directory.
Like this:
C:\Perl\duration.pl
I want it only to display C:\Perl\.
How can I do it?
To get the current working directory (pwd on many systems), you could use cwd() instead of abs_path:
use Cwd qw();
my $path = Cwd::cwd();
print "$path\n";
Or abs_path without an argument:
use Cwd qw();
my $path = Cwd::abs_path();
print "$path\n";
See the Cwd docs for details.
To get the directory your perl file is in from outside of the directory:
use File::Basename qw();
my ($name, $path, $suffix) = File::Basename::fileparse($0);
print "$path\n";
See the File::Basename docs for more details.
Each of the following snippets get the script's directory, which is not the same as the current directory. It's not clear which one you want.
use FindBin qw( $RealBin );
say $RealBin;
or
use Cwd qw( abs_path );
use File::Basename qw( dirname );
say dirname(abs_path($0));
or
use Cwd qw( abs_path );
use Path::Class qw( file );
say file(abs_path($0))->dir;
Use:
print($ENV{'PWD'});
But I think it doesn't work on Windows...
Just remove the '$0'
use Cwd qw(abs_path);
my $path = abs_path();
print "$path\n";
Here is one simple solution:
use Cwd;
my $cwd = cwd();
print "Current working directory: '$cwd()'";
I hope this will help.
You could use FindBin:
use FindBin '$RealBin';
print "$RealBin\n";
FindBin is a standard module that is installed when you install Perl. To get a list of the standard pragmatics and modules, see perldoc perlmodlib.
I used my script in dirs with symlinks.
The script parses the path and executes commands depending on the path.
I was faced with the correct determination of the current path.
Here is example:
root#srv apache # pwd
/services/apache
root#srv apache # readlink -f .
/services/apache2225
Cwd module disclosures path (analogue of readlink -f)
http://perldoc.perl.org/Cwd.html
root#server apache # perl -e 'use Cwd; print cwd . "\n";'
/services/apache2225
If you need to get current path like pwd, you can use $ENV{'PWD'}
root#srv apache # perl -e 'use Cwd; print $ENV{'PWD'}."\n";'
/services/apache
Thank you.

How do I load libraries relative to the script location in Perl?

How can you get current script directory in Perl?
This has to work even if the script is imported from another script (require).
This is not the current directory
Example:
#/aaa/foo.pl
require "../bbb/foo.pl"
#/bbb/bar.pl
# I want to obtain my directory (`/bbb/`)
print($mydir)
The script foo.pl could be executed in any ways and from any directory, like perl /aaa/foo.pl, or ./foo.pl.
What people usually do is
use FindBin '$Bin';
and then use $Bin as the base-directory of the running script. However, this won't work if you do things like
do '/some/other/file.pl';
and then expect $Bin to contain /some/other/ within that. I'm sure someone thought of something incredibly clever to work this around and you'll find it on CPAN somewhere, but a better approach might be to not include a program within a program, but to use Perl's wonderful ways of code-reuse that are much nicer than do and similar constructs. Modules, for example.
Those generally shouldn't care about what directory they were loaded from. If they really need to operate on some path, you can just pass that path to them.
See Dir::Self CPAN module. This adds pseudo-constant __DIR__ to compliment __FILE__ & __LINE__.
use Dir::Self;
use lib __DIR__ . '/lib';
I use this snippet very often:
use Cwd qw(realpath);
use File::Basename;
my $cwd = dirname(realpath($0));
This will give you the real path to the directory containing the currently running script. "real path" means all symlinks, "." and ".." resolved.
Sorry for the other 4 responses but none of them worked, here is a solution that really works.
In below example that adds the lib directory to include path the $dirname will contain the path to the current script. This will work even if this script is included using require from another directory.
BEGIN {
use File::Spec;
use File::Basename;
$dirname = dirname(File::Spec->rel2abs( __FILE__ )) . "/lib/";
}
use lib $dirname;
From perlfaq8's answer to How do I add the directory my program lives in to the module/library search path?
(contributed by brian d foy)
If you know the directory already, you can add it to #INC as you would for any other directory. You might if you know the directory at compile time:
use lib $directory;
The trick in this task is to find the directory. Before your script does anything else (such as a chdir), you can get the current working directory with the Cwd module, which comes with Perl:
BEGIN {
use Cwd;
our $directory = cwd;
}
use lib $directory;
You can do a similar thing with the value of $0, which holds the script name. That might hold a relative path, but rel2abs can turn it into an absolute path. Once you have the
BEGIN {
use File::Spec::Functions qw(rel2abs);
use File::Basename qw(dirname);
my $path = rel2abs( $0 );
our $directory = dirname( $path );
}
use lib $directory;
The FindBin module, which comes with Perl, might work. It finds the directory of the currently running script and puts it in $Bin, which you can then use to construct the right library path:
use FindBin qw($Bin);
You can also use local::lib to do much of the same thing. Install modules using local::lib's settings then use the module in your program:
use local::lib; # sets up a local lib at ~/perl5
See the local::lib documentation for more details.
Let's say you're looking for script.pl. You may be running it, or you may have included it. You don't know. So it either lies in the %INC table in the first case or as $PROGRAM_NAME (aka $0) in the second.
use strict;
use warnings;
use English qw<$PROGRAM_NAME>;
use File::Basename qw<dirname>;
use File::Spec;
use List::Util qw<first>;
# Here we get the first entry that ends with 'script.pl'
my $key = first { defined && m/\bscript\.pl$/ } keys %INC, $PROGRAM_NAME;
die "Could not find script.pl!" unless $key;
# Here we get the absolute path of the indicated path.
print File::Spec->rel2abs( dirname( $INC{ $key } || $key )), "\n";
Link to File::Basename, File::Spec, and List::Util