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

hi, I am not familiar in writing Perl script in Unix. Currently, I need a unix perl script which will keep the latest file in the specific directory and move or copy the rest of the files which exist in the same directory to other directory. How should I write it in a unix Perl script. E.g. In /tmp directory, I have 10 files with diferrent date & time stated. I want to keep the latest file only and the rest 9 files, I will either copy or move to the other directory by passing parameter.
  • Comment on Unix - Keep the last modified file in the directory and move/copy the rest of the files.

Replies are listed 'Best First'.
Re: Unix - Keep the last modified file in the directory and move/copy the rest of the files.
by davorg (Chancellor) on Jun 06, 2003 at 09:43 UTC
    use File::Copy; my $src = '/path/to/source/directory'; my $tgt = '/path/to/target/directory'; opendir SRC, $src or die $!; my @files = sort { -M $a <=> -M $b } readdir SRC; shift @files; move("$src/$_", "$tgt/$_") for @files;

    Update: fixed as noted below.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      I think you'd want to shift @files; rather than pop because -M returns the age of the file in days, not the actual mtime.

      Also, it looks like a last minute name change bit you. That should be readdir SRC; rather than DIR.

      -sauoq
      "My two cents aren't worth a dime.";
      
      my @files = sort { -M $a <=> -M $b } readdir SRC;
      readdir doesn't prepend the SRC directory to the filename for you, so if your cwd is not the source directory, you will get strange results from that code.

      Makeshifts last the longest.

Re: Unix - Keep the last modified file in the directory and move/copy the rest of the files.
by sauoq (Abbot) on Jun 06, 2003 at 09:47 UTC

    Something like the following might get you started. Please understand that it was quickly written and barely tested. I urge you to understand it before using it...

    #!/usr/bin/perl -w use strict; use File::Copy; die "Usage: $0 dir destdir\n" unless @ARGV == 2; my ($dir,$mvto) = @ARGV; opendir DIR, $dir or die "Can't open director $dir: $!\n"; # The ST probably isn't necessary... my @files = map { $_->[1] } # map back. sort { $a->[0] <=> $b->[0] } # sort on mtime map { [ -M $_, $_ ] } # store mtime grep { !/\.\.?$/ } # skip . and .. readdir(DIR); closedir DIR; # The latest is in $files[0]. Move the rest. for ( @files[ 1 .. $#files ] ) { copy "$dir/$_", $mvto; # move "$dir/$_", $mvto; # Don't use move unless you're sure this w +orks. }
    -sauoq
    "My two cents aren't worth a dime.";
    
Re: Unix - Keep the last modified file in the directory and move/copy the rest of the files.
by Anonymous Monk on Jun 06, 2003 at 10:34 UTC

    here's a simplified Unix way.

    $ export LASTFILE=`ls -t | head -n 1` $ for MYFILE in `ls | grep -Ev $LASTFILE` ; do mv $MYFILE newdir; done
Re: Unix - Keep the last modified file in the directory and move/copy the rest of the files.
by zengargoyle (Deacon) on Jun 06, 2003 at 09:48 UTC

    maybe you should try and do it using something you're familiar with. in this case i would probably just use a simple shell script.

    #!/bin/sh ls -t $1 | ( read keepthisone while read movethisone do echo $2 $movethisone $3 done )

    very simple, serves multiple purposes.

    $ ls -1 whacl-* whacl-20030601223002.gz whacl-20030602223002.gz whacl-20030603223003.gz whacl-20030604223003.gz whacl-20030605223003.gz $ ./movem.sh 'whacl-*' whacl-20030604223003.gz whacl-20030603223003.gz whacl-20030602223002.gz whacl-20030601223002.gz $ ./movem.sh 'whacl-*' cp /dev/null cp whacl-20030604223003.gz /dev/null cp whacl-20030603223003.gz /dev/null cp whacl-20030602223002.gz /dev/null cp whacl-20030601223002.gz /dev/null $ ./movem.sh 'whacl-*' mv /path/to/foreverstore mv whacl-20030604223003.gz /path/to/foreverstore mv whacl-20030603223003.gz /path/to/foreverstore mv whacl-20030602223002.gz /path/to/foreverstore mv whacl-20030601223002.gz /path/to/foreverstore $ ./movem.sh 'whacl-*' rm rm whacl-20030604223003.gz rm whacl-20030603223003.gz rm whacl-20030602223002.gz rm whacl-20030601223002.gz $ ./movem.sh 'whacl-*' rm | sh $ ls whacl-* whacl-20030605223003.gz

    take out the 'echo' if you don't want to check your commands before doing them.

      hi zengargoyle, Thanks for your suggestion. I am not familiar with Shell Script as well. But roughly I know what is that about. May I know what are those variables use for & how to use it. 1. $1 , $2 , $3 - what should this variable use for? when to use it? is this a parameter to be pass in when we run the ./movem.sh? 2. keepthisone - what should this variable use for? when to use it? is this a parameter to be pass in when we run the ./movem.sh? or I need to put in the value here? 3. movethisone - what should this variable use for? when to use it? is this a parameter to be pass in when we run the ./movem.sh? or I need to put in the value here? 4. $movethisone - how about this again? Hope to hear from you soon as I am rushing for this script. Thanks. rgds, hyliau
        1. $1 , $2 , $3 - what should this variable use for? when to use it? is this a parameter to be pass in when we run the ./movem.sh?

        yes, they are the parameters, pretend i gave them names.

        2. keepthisone - what should this variable use for? when to use it? is this a parameter to be pass in when we run the ./movem.sh? or I need to put in the value here?

        pretend i called this variable 'the_most_recent_file'.

        3. movethisone - what should this variable use for? when to use it? is this a parameter to be pass in when we run the ./movem.sh? or I need to put in the value here?

        pretend i called this variable 'not_the_most_recent_file'

        #!/bin/sh files_to_check=$1 command_to_run=$2 the_destination=$3 echo "# looking for files matching $files_to_check" # ls -t sorts files by last modification time, most recent to oldest ls -t $files_to_check | ( # the first line will be the most recent file read the_most_recent_file echo "# do nothing with the most recent file: $the_most_recent_file" # the rest of the lines will not be the most recent file echo "# do something with the rest of the files" while read not_the_most_recent_file do echo $command_to_run $not_the_most_recent_file $the_destination done )
Re: Unix - Keep the last modified file in the directory and move/copy the rest of the files.
by Aristotle (Chancellor) on Jun 07, 2003 at 00:40 UTC
    use File::Copy; use File::Spec::Functions qw(catfile); use constant SRCDIR => '/tmp/src'; use constant DESTDIR => '/tmp/dest'; my @file = do { opendir my($dirh), SRCDIR or die $!; readdir $dirh; }; while(@file > 2) { my $tomove = splice @file, (-M $file[0] < -M $file[1] ? 1 : 0), 1; move(catfile(SRCDIR, $tomove), catfile(DESTDIR, $tomove)); }

    Makeshifts last the longest.