In my perl script, I have the param $FILE=/etc/sysconfig/network
in which way (in perl) I can cut only the directory and put the directory in $DIR param
in order to get:
$DIR=/etc/sysconfig
(like dirname /etc/sysconfig/network in shell script)
Watch out! dirname() is deliberately dumb to emulate the dirname shell command. It is not so much "give me the directory part of this file path" as "give me all but the last part of this path". Why is that important?
my $dir = "/foo/bar/"; # obviously a directory
print dirname($dir); # prints /foo
This is fine, just so long as you realize that dirname does not return the dirname.
If you want the above to return /foo/bar/ you're better off using File::Spec.
use File::Spec;
my($vol,$dir,$file) = File::Spec->splitpath($path);
use File::Basename;
($name,$path,$suffix) = fileparse($fullname,#suffixlist);
$name = fileparse($fullname,#suffixlist);
$basename = basename($fullname,#suffixlist);
$dirname = dirname($fullname);
Read more about File::Basename in perldoc.
Use the File::Basename core module:
use strict;
use warnings;
use File::Basename;
my $FILE = '/etc/sysconfig/network';
my $DIR = dirname($FILE);
print $DIR, "\n";
This prints out:
/etc/sysconfig
Related
i need to copy files with specific extensions. but the problem is there are multiple files with same file name.i dont want to overwrite them and store as copy like file _1,file_2 etc. when i tried using unix command line the files are overwitten though i used cp -n.
is there any way i can do this task using command line or perl ?
the command i used was
find -L . -name "*.txt" -exec cp -n {} -t ~/destination
You can also use the cp --backup=numbered option.
In Perl (untested)
perl -MFile::Copy=cp -e '-e ($n = "~/destination/$_") or cp $_, $n for #ARGV' *.txt
The below perl script recursively finding the files and copying into the destination folders however if already exists it will rename the file as filename_1, filename_2
#!/usr/bin/perl
use strict;
use warnings;
use File::Find;
use File::Spec::Functions qw'catfile';
use File::Copy qw'move';
#use autodie qw'move';
use File::Basename;
my ($filename);# = 'DUMBFILE';
my $origin = '/home/itadmin/FoldersFind/OriginalFolder';
my $destination = '/home/itadmin/FoldersFind/Destination';
mkdir($destination, 0777);
my ($path);
find(\&wanted, $origin);
sub wanted
{
if(-e $origin)
{
if($File::Find::name=~m/\.(txt|html|xml)$/gs)
{
$filename = basename($File::Find::name);
}
}
$path = "$destination/$filename";
my $cnt;
while(-e $path)
{
$cnt++;
$path = catfile $destination, "$filename.$cnt";
}
move($filename, $path);
}
Input: (Fetching files may be duplicate)
/OriginalFolder/<folders1>/*file
/OriginalFolder/<folders2>/*file
Output: (Renaming)
/Destination/*file_<count> #/Destination/*file_1
/Destination/*file_<count> #/Destination/*file_2
I am trying to access all sub-folders in the current working directory. And then I want to run a program in each sub-folder. How can I do this? My code gave the following error:
Too many arguments for glob at ./analysis.pl line 13, near ""08")"
BEGIN not safe after errors--compilation aborted at ./analysis.pl line 13.
#!/usr/bin/perl
use File::chdir;
use strict;
use warnings;
use Cwd;
# current working directory
my $dir = cwd();
# subfolders pathway
my #dirs = glob ($dir/*);
# input file for program
my $data="ethanol.txt";
# enter to each subfolder
foreach $dir ( #dirs ) {
chdir($dir) or die "Cannot cd to $dir: $!\n";
# Run for ethanol
system("echo 1 1 | program -o $data");
chdir("..");
}
I think what you actually meant to say was, glob("$dir/*"), but I like using File::Find::Rule for this type of task:
#!/usr/bin/env perl
use strict;
use warnings;
use Cwd;
use File::Find::Rule;
my $dir = cwd();
my #subdirs = File::Find::Rule->directory
->in( $dir );
foreach my $subdir ( #subdirs ) {
# do stuff
}
I notice that you have loaded File::chdir but fon't use it in your program. It can be a very useful module, and is particularly applicable in this situation. It works by defining a magic variable $CWD that evaluates to the current directory when read, and alters the current directory when written to. That means it can replace Cwd and chdir.
In addition, you can use local to localise changes to the working directory so that the original location is restored at the end of a block.
Take a look at this rewrite of your own code that should do what you need.
use strict;
use warnings;
use File::chdir;
my $data = 'ethanol.txt';
while (my $node = glob '*' ) {
next unless -d $node;
local $CWD = $node;
system "echo 1 1 | program -o $data";
}
I have a bunch of data that is stored in sub-directories labeled by date. I have used the Cwd command to get the Current working directory so that I can then print it to the vi file that I am writing with the recovered data from the sub-directories. I am using the Cwd as a prefix to the data strings. Is there a way to print only the current directory name and not the path?
example:
Instead of printing-
/d2/aschwa/archive_data/METAR_data/20120302KDUX 121255Z.........
Is there a way to print only-
20120302KDUX 121255Z.........
Here's the code I'm using-
use strict;
use warnings;
use file::find;
use Cwd;
my #folder = ("/d2/aschwa/archive_project/METAR_data/");
open( OUT , '>', 'KDUX_METARS.txt') or die "Could not open $!";
print OUT "Station, Day/Time, Obs Type, Wind/Gust, Vis, Sky, T/Td, Alt, Rmk\n";
print STDOUT "Finding METAR files\n";
my $criteria = sub {if(-e && /^2012/) {
open(my $file,$_) or die "Could not open $_ $!\n";
my $dir = getcwd;
while(<$file>) {
print OUT $dir,$_ if /KDUX ....55Z|KDUX ....05Z/;
}
}
};
find($criteria, #folder);
close OUT;
In Perl, you can use functions basename or fileparse to extract the file name from a path.
They are included in the core module File::Basename.
Simply split, then pop.
Shamelessly stolen from perlmonks:
$ perl -e 'print pop #{[split m|/|, "/home/bin/scripts/test.pl"]};'
test.pl
Reference link: http://www.perlmonks.org/?node_id=241089
You can combing the perl module File::Basename with Cwd to get the directory without the path
perl -MCwd -MFile::Basename -e 'my $dir = cwd; print basename($dir)'
Why don't you just get the content after the last slash with a regexp like below:
$path = '/d2/aschwa/archive_data/METAR_data/20120302KDUX 121255Z.........';
$path = $1 if $path =~ m~/([^/]*)/?$~;
This is in my opinion the best way to do it. The above code is just an example, but the regexp there will do the job you want.
I have a segment of code that is working that finds all of the .txt files in a given directory, but I can't get it to look in the subdirectories.
I need my script to do two things
scan through a folder and all of its subdirectories for a text file
print out just the last segments of its path
For example, I have a directory structed
C:\abc\def\ghi\jkl\mnop.txt
I script that points to the path C:\abc\def\. It then goes through each of the subfolders and finds mnop.txt and any other text file that is in that folder.
It then prints out ghi\jkl\mnop.txt
I am using this, but it really only prints out the file name and if the file is currently in that directory.
opendir(Dir, $location) or die "Failure Will Robertson!";
#reports = grep(/\.txt$/,readdir(Dir));
foreach $reports(#reports)
{
my $files = "$location/$reports";
open (res,$files) or die "could not open $files";
print "$files\n";
}
I do believe that this solution is more simple and easier to read. I hope it is helpful !
#!/usr/bin/perl
use File::Find::Rule;
my #files = File::Find::Rule->file()
->name( '*.txt' )
->in( '/path/to/my/folder/' );
for my $file (#files) {
print "file: $file\n";
}
What about using File::Find?
#!/usr/bin/env perl
use warnings;
use strict;
use File::Find;
# for example let location be tmp
my $location="tmp";
sub find_txt {
my $F = $File::Find::name;
if ($F =~ /txt$/ ) {
print "$F\n";
}
}
find({ wanted => \&find_txt, no_chdir=>1}, $location);
Much easier if you just use File::Find core module:
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
use File::Find;
my $Target = shift;
find(\&survey, #ARGV);
sub survey {
print "Found $File::Find::name\n" if ($_ eq $Target)
}
First argument: pathless name of file to search for. All subsequent arguments are directories to check. File::Find searches recursively, so you only need to name the top of a tree, all subdirectories will automatically be searched as well.
$File::Find::name is the full pathname of the file, so you could subtract your $location from that if you want a relative path.
I have a list of file names in a txt file. They correlate to pdfs I have. I would like to copy the actual pdf files that are listed in that list, to a directory. The files that need to be copied are contained in different subdirectories as well. What is the easiest way to do this using perl?
Thanks!
I'd recommend that you read perlfaq5: How do I copy a file?
After that, it shouldn't be too hard; Untested code:
use strict;
use warnings;
use 5.010;
use autodie;
use File::Copy;
use File::Spec;
open my $files_fh, '<', '/path/to/txt';
my $files_dir = shift // '/path/to/dir';
my $destination_dir = shift // '/path/to/dir';
while (<$files_fh>) {
chomp;
next unless -d (my $file = File::Spec->catfile($files_dir, $_) );
copy($file, $file . '.cpy');
move($file . '.cpy', $destination_dir);
say "Copied [$file] and moved it to [$destination_dir]";
}
I would recommend that you use the perl File::Copy package.
use File::Copy;
$filetobecopied = "myhtml.html.";
$newfile = "html/myhtml.html.";
copy($filetobecopied, $newfile) or die "File cannot be copied.";