Sam Weisenthal
Sam Weisenthal

Reputation: 2951

Can't find file trying to move

I'm trying to clean up a directory that contains a lot of sub directories that actually belong in some of the sub directories, not the main directory.

For example, there is

Main directory
     sub1
     sub2
     sub3     
     HHH

And HHH belongs in sub3. HHH has multiple text files inside of it (as well as some ..txt and ...txt files that I would like to ignore), and each of these text files has a string

  some_pattern [sub3].

So, I attempted to write a script that looks into the file and then moves it into its corresponding directory

use File::Find;

use strict;
use warnings;

use File::Copy;

my $DATA = "D:/DATA/DATA_x/*";
my @dirs = grep { -d } glob $DATA;

foreach (@dirs) {

  if ($_ =~ m/HHH/) {
    print "$_\n";
    my $file = "$_/*";
    my @files = grep { -f } glob $file;

    foreach (@files) {
      print "file $_\n";
    }

    foreach (@files) {
      print "\t$_\n";
      my @folders = split('/', $_);

      if ($folders[4] eq '..txt' or $folders[4] eq '...txt') {
        print "$folders[4] ..txt\n";
      }

      foreach (@folders) {
        print "$_\n";
      }

      open(FH, '<', $_);
      my $value;
      while (my $line = <FH>) {
        if ($line =~ m/some_pattern/) {
          ($value) = $line =~ /\[(.+?)\]/;
          ($value) =~ s/\s*$//;
          print "ident'$value'\n";
          my $new_dir = "$folders[0]/$folders[1]/$folders[2]/$value/$folders[3]/$folders[4]";
          print "making $folders[0]/$folders[1]/$folders[2]/$value/$folders[3]\n";
          print "file is $folders[4]\n";
          my $new_over_dir = "$folders[0]/$folders[1]/$value/$folders[2]/$folders[3]";
          mkdir $new_over_dir or die "Can't make it $!";
          print "going to swap\n '$_'\n for\n '$new_dir'\n";
          move($_, $new_dir) or die "Can't $!";
        }
      }
    }
  }
}

It's saying

Can't make it No such file or directory at foo.pl line 57, <FH> line 82.

Why is it saying that it won't make a file that doesn't exist?

A while later: here is my final script:

use File::Find;

use strict;
use warnings;

use File::Copy;

my $DATA = "D:/DATA/DATA_x/*";
my @dirs = grep { -d } glob $DATA;

foreach (@dirs) {

  if ($_ =~ m/HHH/) {
    my $value; 
    my @folders;
    print "$_\n";
    my $file = "$_/*";
    my @files = grep { -f } glob $file;

    foreach (@files) {
      print "file $_\n";
    }

    foreach (@files) {
      print "\t$_\n";
      @folders = split('/', $_);

      if ($folders[4] eq '..txt' or $folders[4] eq '...txt') {
        print "$folders[4] ..txt\n";
      }

      foreach (@folders) {
        print "$_\n";
      }

      open(FH, '<', $_);
      while (my $line = <FH>) {
        if ($line =~ m/some_pattern/) {
          ($value) = $line =~ /\[(.+?)\]/;
          ($value) =~ s/\s*$//;
          print "ident'$value'\n";
        }
      }


      }
        if($value){
        print "value $value\n";
        my $dir1 = "/$folders[1]/$folders[2]/$folders[3]/$folders[4]/$folders[5]";
    my $dir2 = "/$folders[1]/$folders[2]/$folders[3]/$folders[4]/$value";
        system("cp -r $dir1 $dir2");
      } 

    }
  }
}

This works. It looks like part of my problem from before was that I was trying to run this on a directory in my D: drive--when I moved it to the C: drive, it worked fine without any permissions errors or anything. I did try to implement something with Path::Tiny, but this script was so close to being functional (and it was functional in a Unix environment), that I decided to just complete it.

Upvotes: 1

Views: 150

Answers (2)

clt60
clt60

Reputation: 63972

You really should read the Path::Tiny doccu. It probably contains everything you need.

Some starting points, without error handling and so on...

use strict;
use warnings;
use Path::Tiny;

my $start=path('D:/DATA/DATA_x');
my $iter = path($start)->iterator({recurse => 1});

while ( $curr = $iter->() ) {

    #select here the needed files - add more conditions if need
    next if $curr->is_dir;  #skip directories
    next if $curr =~ m/HHH.*\.{2,3}txt$/;   #skip ...?txt

    #say "$curr";
    my $content = $curr->slurp;
    if( $content =~ m/some_pattern/ ) {
        #do something wih the file
        say "doing something with $curr";

        my $newfilename = path("insert what you need here"); #create the needed new path for the file ..
        path($newfilename->dirname)->mkpath; #make directories
        $curr->move($newfilename);           #move the file
    }
}

Upvotes: 2

sateesh
sateesh

Reputation: 28713

Are you sure of the directory path you are trying to create. The mkdir call might be failing if some of the intermediate directories doesn't exist. If your code is robust to ensure that the variable $new_over_dir contains the directory path you have to create, you can use method make_path from perl module File::Path to create the new directory, instead of 'mkdir'.

From the documentation of make_path:

The make_path function creates the given directories if they don't exists before, much like the Unix command mkdir -p.

Upvotes: 1

Related Questions