Unable to copy multiple files to a directory using Perl script - perl

One wierd behaviour I am observing -- in a perl script , I checked wether a directory exists or not, if it exists - it copies a file to that directory, if it doesnt -then the directory is created followed by the file copy
When I go and check the file manually, the file is present . but when I run the same script again to copy another file using the same process as above, I see that the previous files arent present. For a confirmation , I performed a directory read in the script , it said that dir is empty.
Can anyone please help me in understanding
Please find below a code :
if (-d "/home/foo") {
print "the directory is already created \n";
$i=0;
opendir(DIR, "/home/foo") or die "Cant open /home/foo: $!\n";
#list = readdir(DIR);
foreach $line(#list) {
unless ($line =~ /^[.][.]?\z/) {
$i++;
}
}
if ($i != 0) { print "There is Stuff in here!"; }
else { print "This Dir is Empty!"; }
closedir(DIR);
}
else {
&runcond("mkdir /home/foo");
}
`cp $file /home/foo`; #Copying a file $file in the directory

`cp $file /home/foo`;
You haven't defined $file

Related

How can I resolve error: no such file or directory

I am trying to read a FASTA file using perl and I want to put each header as the key and each sequence as the value into hash. I wrote my codes but I got error: no such file or directory
I have my fasta file and perl file in the same directory.
here is my code
#!/usr/bin/perl
use strict;
my $file = "chicken.fa";
open (my $READ, "<$file") || die "Cannot open $file: $!.\n";
my %seqs = ();
my $header = '';
while (<$READ>){
my $line = $_;
chomp($line);
if ($line eq "") { next; }
if ($line =~ /^>.+/){
$line = $header;
} else {
$seqs{"$header"} .= $line;
}
}
close ($READ);
If you are certain that a file called chicken.fa does exist, there are several possibilities.
Wrong directory. As written your script will try to find the chicken.fa file in the same directory that you are running the Perl script from. If the file is actually in a different directory, it won't be found.
if (! -f 'chicken.fa') {
warn "'chicken.fa' doesn't exist in this directory!";
}
Even if your perl script and input file are in the same directory, Perl won't find your file unless you also start the perl script from that directory. That is, this will work
cd /directory/where/the/stuff/is
perl the_script.pl
but this won't
cd /some/other/directory
perl /directory/where/the/stuff/is/the_script.pl
Permission. You may not have the required permissions, in this case read permission, to open the file.
if (! -r 'chicken.fa') {
warn "Don't have read permission on 'chicken.fa' file!";
}
Bad symbolic link. Maybe chicken.fa is a symbolic link to another location, and that location is not a valid file.
if (-l 'chicken.fa' && ! -f readlink('chicken.fa')) {
warn "'chicken.fa' is an invalid symbolic link";
}

If file exists with wildcard?

I need to verify if a file exists, but the file name changes. At least the last part of the file name does due to appending time (hh-mm-ss).
So basically, I need to see if file yyyy-MM-dd-hh-mm-ss exists irrespective of what the hh-mm-ss is.
I'm trying to do a wildcard search but it doesn't find the file.
For example, I want to check if the file /home/httpd/doc/$user/$year/2018-08-20-* exists.
Is it possible to use * for the filename variable? Or an other better way?
I'm trying to check if a file exists, but with a wildcard. Here is my code:
opendir(DIR, "/home/httpd/doc/$user/2018") || die "Unable to open log/location";
while(<>){
if($_ =~ /\/2018-08-20-\d+-\d+-\d+/) {
print "file exists\n";
}
}
It looks like you are trying to use the opendir-readdir pattern, which would look like
opendir(DIR, "/home/httpd/doc/$user/2018") || die "Unable to open log/location";
foreach my $file (readdir DIR) {
if ($file =~ /\/2018-08-20-\d+-\d+-\d+/) {
print "file exists\n";
}
}
closedir DIR;
but a more concise way (with more edge cases but would probably work in your case) would be to use glob
if (glob("/home/httpd/doc/$user/2018/2018-08-20-*")) {
print "file exists\n";
}

File managing issues

im working on a simple script to rename & move files into a new directory. I can't seem to get it work properly, basically if the folder is already created it will moves the files into it only if the files are renamed, if the folder is already created but files need to be renamed it won't work it will just rename the files and give me an error because it won't be able to move the files. If the folder need to be created and files to be renamed it will create the folder and rename the files but it won't be able to move them. So i am a bit lost really..
http://i.stack.imgur.com/v8smp.jpg
I've been trying a lot of different way but it ends up not working or giving me the same result i think i am doing something wrong, heres my code :
use strict;
use warnings;
use File::Copy qw(mv);
my ($movie, $season, $cont) = #ARGV;
if (not defined $movie) {
die "need a name as first argument\n";
}
if (defined $movie and defined $season and defined $cont) {
print "\n\nProcessing $movie season $season with container .$cont :\n";
my $npath = "Saison "."$season";
my $exist = 0;
my $num = 1;
my $ind = 0;
my $flast = undef;
my $rpath = undef;
my #files = glob("*.$cont");
my #all = glob('*');
foreach my $f (#files) {
if ($f =~ m/e([0-1_-] ?)\Q$num/i or $f =~ m/episode([0-1_-] ?)\Q$num/i) {
$flast = "$movie.S$season"."E$num.$cont";
rename($f, $flast) or die "\nError while renaming $f !";
$num++;
}
}
if (-d "$npath") {
$exist = 1;
print "\n$npath";
}
else {
mkdir($npath) or die "\nError while making new directory";
$exist = 1;
}
sleep(1);
if ($exist == 1) {
foreach my $f (#files) {
$npath = "Saison "."$season/$f";
mv($f, $npath) or die "\nError while moving $f";
print "\n$f done !";
$ind++;
}
print "\n\n$ind files processed successfully !";
}
}
The problem is that you are renaming the files and then moving them, but after the rename the file no longer exists under its old name in the #files array
You can use mv to change the name of the file as well as putting it into a new directory. In other words, you can call
mv 'movie.title.s01.e08.(2008).[1080p].mkv', 'Saison 01/Movie TitleS01E08.mkv'
which simplifies your program considerably. You just need to create the new directory if it doesn't exist, and then call mv $f, "$npath/$flast" for each name in #files

How to link zip folders to newly created folder

I am trying to copy data from a folder (named Zip) to a set of newly created folders.
Zip folder content is:
SO_90_X_L001_R1.fastq.gz
SO_100_X_L001_R1.fastq.gz
SO_101_X_L001_R1.fastq.gz
and I have created the following empty folders:
SO_90
SO_100
SO_101
Without giving keyboard input, is it possible to copy those zipped files to matching folders using Perl?
i tryed below script, than also i am not getting proper output.
#!usr/bin/perl
use File::Copy "cp";
open(my $F, "a.txt") or die("cant open a.txt\n");
while(<$F>)
{
next unless /\S/;
mkdir $_ ;
}
close($F);
for my $file (<SO_/*.fastq.gz>){
print $_;
if( $file =~ m!SO_/(.*)_X_L001_R1.fastq.gz! ) {
mkdir($_); # comment this line if not necessary
cp($file, "$1/") or warn("Copy '$file, $1' failed\n");
} else {
warn("$file is not ending in '_X_L001_R1.fasta.gz'\n");
}
}
I am writing a new answer because we the question is in fact different.
We have several files like ZIP/SO_100_X_L001_R1.fastq.gz to copy to
SO_100/....
#!/usr/bin/perl
use File::Copy "cp";
for my $file (<ZIP/*.fastq.gz>){
print $_;
if( $file =~ m!ZIP/(.*)_X_L001_R1.fastq.gz! ) {
mkdir($1); # comment this line if not necessary
cp($file, "$1/") or warn("Copy '$file, $1' failed\n");
} else {
warn("$file is not ending in '_X_L001_R1.fasta.gz'\n");
}
}
Edit: I added some "warnings" in order to help with the debug
perl -nle 'mkdir $_ if /\S/' a.txt
-l to remove \n from folder names (otherwise folder name would be SO_100\n)
if /\S/ to skip possible empty-lines in the input file
(your question changed....) Update: If you need more complex processing, you may build a script where you can include someting like:
open(my $F, "a.txt") or die("cant open a.txt\n");
while(<$F>){
chomp;
next unless /\S/;
mkdir $_ ;
#... do other things related with this folder...
}
close $F;

Copy files from one folder to another based on similar file name

I trying to write a script that will copy files from one folder to another based on the file name(similar). As I got Few thousands text files in a folder. But I try to find few hundreds of files out of thousands files. It's takes a lot of time to search it one by one.
Copy seem like a good idea to use in this and then use for to loop through the list of files that I try to find out of thousands. But Copy need a specified name. The problem is I only have part of the file name.
Example of list of files(Content of the text file):
ABCDEF-A01
ADEWSD-B03
ABDDER-C23
Example of filename:
GGI_1409506_ABCDEF-A01.txt,GGI_ADEWSD-B03.txt,DA_ABDDER-C23_12304.txt
I only got the ABCDEF-A01 instead of the full filename.
Expected result:
Able to search through the folder and copy the files to another location that matched according the list of files (one text files).
Anything that you can share? Info/ans/related posts? Thank you so much!
Try the below code in perl . When running the program pass the arguments for Source Directory path and Destination Directory path along with the list of filename that need to be searched. If destination directory doesn't exist it will create a folder automatically through the program as shown below :
Code:
use strict;
use warnings;
use File::Copy;
my $source = $ARGV[0];
my $destination = $ARGV[1];
my $listFiles = $ARGV[2];
if(-f $destination)
{
print "Already unknown extension of file exists with the same name of directory. So rename the file and run the program";
exit 0;
}
if(-d "$destination")
{
print "Directory where files need to be copied: $destination\n";
}
else
{
print "No Directory found and hence created the directory $destination\n";
mkdir("$destination");
}
opendir DIR, $source or die "cant open dir";
my #files = grep /(.*?)(\.txt)$/,(readdir DIR);
open my $fh, '<', "$listFiles" or die "Cannot open the file names to search $listFiles - $!";
open my $out,'>', "$ARGV[1]\\NoMatch.txt" or die "Cannot write to the file NoMatch.txt - $!";
my #listFileNames = <$fh>;
my #listFiles = ();
foreach my $InputFiles (#files)
{
chomp($InputFiles);
foreach my $list(#listFileNames)
{
chomp($list);
if($InputFiles =~ /$list/isg)
{
print "Files : $InputFiles copying\t";
copy("$InputFiles","$destination");
print "Files : $InputFiles copied\n";
push(#listFiles,$list);
}
}
}
my %seen = ();
my $count = 0;
foreach my $list (#listFiles)
{
$seen{lc($list)} = 1;
#print $list . "\n";
}
foreach my $listnames (#listFileNames)
{
if($seen{lc($listnames)})
{
}
else
{
if($count ==0)
{
print "\nFilenames that did not match the text files are present in the destination folder : NoMatch.txt file " . "\n";
}
print $out "$listnames\n";
$count++;
}
}
close($out);
close($fh);
closedir(DIR);
create a batch file and put it in the source folder, with your list of files you want to copy.
for /f %%f in (list.txt) do robocopy c:\source d:\dest %%f
Hope this helps
#!/usr/bin/perl -w
use strict;
use File::Copy;
my $sorce_direcrtory = qq{};
my $new_directory = "";
opendir(my $dh, $sorce_direcrtory) || die;
while(readdir $dh) {
if($_ =~ /[A..Z]+\-[A..Z]\d+/){
move("$sorce_direcrtory/$_", "$new_directory/$_");
}
}
closedir $dh;