Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Move a file to another directory based on regex match

by DAN0207 (Acolyte)
on Feb 25, 2021 at 14:43 UTC ( #11128782=perlquestion: print w/replies, xml ) Need Help??

DAN0207 has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to match the regex of the filename and if it matches i want to move the file into another directory.But when i run the script, i get the error as "move failed: Invalid cross-device link".Please help me.The code is given below:

#!/usr/bin/perl -w use File::Copy; $InDir = $ARGV[0]; $OutDir = $ARGV[1]; if (!opendir(DIR,$InDir)) { print "Bad Dir $InDir\n"; exit 1;} while(my $Infile = readdir(DIR)) { if ($Infile =~ 'F\d{8}\.\d{4}\+\d{4}\-\d{4}\+\d{4}_.*') { move("$Infile", "$OutDir") or die "move failed: $!"; } elsif ($Infile =~ 'F\d{8}\.\d{6}\+\d{4}\-\d{6}\+\d{4}_.*' ) { <.....do something........> } }

Replies are listed 'Best First'.
Re: Move a file to another directory based on regex match
by haukex (Bishop) on Feb 25, 2021 at 14:57 UTC

    The error message is strange, but I do see one issue with your code: readdir returns just the filenames without the directory name. I'd recommend you use File::Spec::Functions qw/catfile/; and move( catfile($InDir,$Infile), $OutDir ). If that fixes the issue, then perhaps the error message is just wrong (is this Windows or some OS other than *NIX?), and if it's doesn't fix the issue, please let us know Update: along with more information about $InDir and $OutDir. Also, Use strict and warnings!

      In fact, the documentation about readdir mentions the fact that you need to prepend the directory again.

      Just in the (very unlikely) case that the files actually exist, the error message suggests that the OP is trying to move them across mount points. This would happen for example if you have two disks mounted below /mount:

      /mount/hda/dir1 /mount/hdb/dir2

      Then, moving files from /mount/hda/dir1 to /mount/hdb/dir2 would mean actually copying the bytes between the two devices. At least the mv program (and thus, maybe also the rename() syscall?) on my Debian system does such copying nowadays...

        actually copying the bytes between the two devices. At least the mv program (and thus, maybe also the rename() syscall?) on my Debian system does such copying nowadays...

        It's a good thing OP is using File::Copy, since that actually does copy the bytes (and only when necessary, AFAIK) - I belive this is what the OS's mv does too. I just tried rename across filesystems and did in fact get the Invalid cross-device link error.

        So maybe the detection of the sameness of the device doesn't work correctly in MSWin?

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      Thank you. I tried as per your kind suggestion , but didnt work. My $InDir value is /spool/input/parse and $OutDir is /spool/input/parsed

        Thank you. I tried as per your kind suggestion , but didnt work. My $InDir value is /spool/input/parse and $OutDir is /spool/input/parsed

        Still a bit strange. Could you please try the following things / give us the following information?

        • Try picking a fixed pair of paths and see if perl -wMstrict -MFile::Copy -e 'move("/spool/input/parse/FILENAME","/spool/input/parsed") or die $!' produces the same error
        • Show the output of perl -V
        • Show the output of perl -MFile::Copy -le 'print $File::Copy::VERSION'
        • Show the output of ls -ld /spool /spool/input /spool/input/parse*
        • Show the output of mount | grep spool
        • Let us know how you're running this script, e.g. from the command line, from cron, from a webserver, from some other script or a batch file, some other job scheduler, etc.?
Re: Move a file to another directory based on regex match
by hippo (Chancellor) on Feb 25, 2021 at 14:56 UTC

    Best guess without data: whatever you have chosen for $OutDir is either an invalid link to a different device, or one of its parents is. Try using /tmp as $OutDir and see if it works there.


    🦛

      I used /tmp as $OutDir .But still the same error "move failed: Invalid cross-device link"

        How odd. Try this SSCCE which works fine for me.

        #!/usr/bin/env perl use strict; use warnings; use File::Copy 'move'; my $indir = '/tmp/foo'; my $outdir = '/tmp/bar'; mkdir $indir; mkdir $outdir; for my $f (qw/a b c/) { open my $out, '>', "$indir/$f" or die "Opening $f: $!"; print $out 'Woo-hoo!'; close $out; } opendir my $dir, $indir or die "Bad Dir $indir: $!"; while (my $infile = readdir ($dir)) { if ($infile =~ /b/) { print "Moving '$infile' ...\n"; move ("$indir/$infile", $outdir) or die "move failed: $! moving $indir/$infile to $outdir" +. " while we are in $ENV{PWD}\n"; } else { print "Skipping '$infile' ...\n"; } }

        🦛

Re: Move a file to another directory based on regex match
by Marshall (Canon) on Feb 25, 2021 at 21:35 UTC
    Start simple:
    I may be wrong, but I think your regex is wrong.
    '+' is not a valid file name character.
    Start by printing the proposed files to be moved:
    I don't know what \+ means?
    #!/usr/bin/perl use strict; use warnings; use File::Copy; my ($inDir, $outDir) = @ARGV; opendir (DIR, $inDir) or die "Bad Input Directory $inDir $!\n"; while (my $infile = readdir(DIR)) { if ($infile =~ 'F\d{8}\.\d{4}\+\d{4}\-\d{4}\+\d{4}_.*') #like F12345678.1234+1234-9876+3456..... { print "$inDir/$infile\n"; } }
      '+' is not a valid file name character.

      yes it is. read the thread. this isnt windows.

        No issue on Windows 10 either in Windows Powershell with vim x+v.

      Thanks a ton!! It worked. I was missing on many other things which i cleared from your suggestions.

Re: Move a file to another directory based on regex match
by Anonymous Monk on Feb 25, 2021 at 15:46 UTC
    I would start by printing the values of $Infile and $Outdir so that you can be sure of what you are asking File::Copy to do. Also be sure that the destinations are not symbolic links to other devices. File::Copy is supposed to first attempt a rename, then fall back to a move. What are the characteristics of the actual things when this error happens?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11128782]
Approved by haukex
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2021-04-15 03:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?