Loading ...
Sorry, an error occurred while loading the content.

Problems with a sequential file deleter

Expand Messages
  • Scott Spencer
    Regards all, I am new to the list. My name is Scott and I am a a Computer Animation student at The Savannah College of Art and Design in Savannah, GA USA. I
    Message 1 of 4 , Apr 18, 2003
    • 0 Attachment
      Regards all,

      I am new to the list. My name is Scott and I am a a Computer
      Animation student at The Savannah College of Art and Design in
      Savannah, GA USA.
      I would like to ask a question of the list please. I was refered to
      you from Usenet users who spoke highly of this group. I am
      (obviously) a new Perl user...brand new...no experience at all : )
      The script I am trying to write will take the contents of a given
      directory, which will actually be a numbered sequence of tiff files
      output from premiere (ie tif001.tif tif002.tif tif003.tif ... etc).
      The script will take every sixth numbered frame and delete those
      inbetween, so when you had file001 - 12 you will end up with file 001
      and 006 and 0012. I hope this is clear.

      So the script follows... I am so twisted up backwards at this point I
      dont know where I am going wrong. I poster two versions of the code,
      one using a foreach statement the other using just a while loop.

      Thanks in advance,

      Scott Spencer

      CODE FOLLOWS************************


      VERSION ONE

      #perl script to sort and delete frames from a tiff sequence in
      premiere.


      ##variables
      $current_file; #filename unedited so it can be deleted if
      needed
      $current_file_number; #current number you are working on
      $current_count = 0; #counter to tell which array element to pull
      $file_counter = 001; #next file to keep
      $file_counter_control = 6; #6 is added to file counter to generate
      the next file # to keep
      $end_frame; #user specified end frame

      ## get the path from stantard input then chomp the trailing newline
      print "please enter path, use format /directory_name : ";
      $path = <STDIN>;
      chomp ($path);
      print "Please enter end frame number";
      $end_frame=<STDIN>;
      chomp ($end_frame);

      opendir (BOOGER, "$path") || die "cannot open your request??? $!";
      #open a directory


      #handle to specified path
      @thefiles = readdir(BOOGER); #read the directory contents
      into an array



      foreach $current_file (@thefiles) {

      $current_file_number = $current_file;
      $current_file_number =~ s/\D*//; #regular expression to
      remove all alpha characters before numbers

      if ($current_file_number ne $file_counter) {
      unlink ($current_file);
      } #end if
      $file_counter = $current_file_number+5;

      #$file_counter = $file_counter + $file_counter_control;


      }

      #### This is a second example in which I used foreach instead of
      ####while, is this a better idea?

      #perl script to sort and delete frames from a tiff sequence in
      premiere.


      ##variables
      $current_file; #filename unedited so it can be deleted if
      needed
      $current_file_number; #current number you are working on
      $current_count = 0; #counter to tell which array element to pull
      $file_counter; #next file to keep
      $file_counter_control = 6; #6 is added to file counter to generate
      the next file # to keep
      $end_frame; #user specified end frame

      ## get the path from stantard input then chomp the trailing newline
      print "please enter path, use format /directory_name : ";
      $path = <STDIN>;
      chomp ($path);
      print "Please enter end frame number";
      $end_frame=<STDIN>;
      chomp ($end_frame);

      opendir (HANDLE, "$path") || die "cannot open your request??? $!";
      #open a directory


      #handle to specified path
      @thefiles = grep -f "$path/$_", readdir(HANDLE); #read the directory
      contents into an array
      closedir HANDLE;

      print @thefiles;


      foreach $current_file (@thefiles) {

      $current_file_number = $current_file;
      $current_file_number =~ s/\D*//; #regular expression to
      remove all alpha characters before numbers

      if ($current_file_number != $file_counter) {
      unlink ($current_file);
      } #end if
      $file_counter = $current_file_number+5;

      #$file_counter = $file_counter + $file_counter_control;

      }
    • Charles K. Clarkson
      ... Welcome. ... You don t mention whether the files will always start in sequence from 001. I made the assumption that they would. You did say they were
      Message 2 of 4 , Apr 19, 2003
      • 0 Attachment
        Scott Spencer <scott@...> wrote:

        : I am new to the list.

        Welcome.

        : The script will take every sixth numbered frame and
        : delete those in between, so when you had file001 - 12
        : you will end up with file 001 and 006 and 0012. I
        : hope this is clear.

        You don't mention whether the files will always start
        in sequence from 001. I made the assumption that they
        would. You did say they were sequential, so I assumed the
        saved files would always be 001, 006, 012, 018, etc.
        You would never, for instance, save files 002, 007, 013,
        etc.

        ============

        Instead of repairing your current script I decided to
        lay down some basics and start a new one. One of the
        first items mentioned to beginners is the use of
        strictures and warnings.

        #!/usr/bin/perl

        use strict;
        use warnings;

        These two modules will force you to be a little more
        disciplined in your script writing. Among many other
        items, there is a need to use the 'my' function when
        first using a variable.

        my $value = 12;
        $value++;

        If we leave the 'my' function out, we'll get errors
        on execution.

        Global symbol "$value" requires explicit package name at aa.pl line 6.
        Global symbol "$value" requires explicit package name at aa.pl line 7.
        Execution of aa.pl aborted due to compilation errors.

        ============

        Variable defined (declared) with 'my' are called
        "lexical variables". Lexical variables can be undefined
        to free up memory. If they are defined within a code
        block, they are automatically undefined when the block
        ends (unless a reference to them remains).

        my $value = 12;
        {
        my $value = 10;
        print "$value\n";
        }
        print "$value\n";


        Prints

        10
        12

        ============

        Now let's look at a part of your problem. How do
        we find every sixth element of a series? First we'll
        create an array of integers from 1 to 12.

        my @values = 1 .. 12;

        Now we'll cycle through them one at a time and
        print them.

        foreach my $value ( @values ) {
        print "$value\n";
        }

        Prints

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12

        Next, we'll change the print to reflect the
        value and a computed variable. Stick with me here.
        I'm getting to something. (Really!)

        printf "%s -> %s\n", $value, $value % 6;

        Prints

        1 -> 1
        2 -> 2
        3 -> 3
        4 -> 4
        5 -> 5
        6 -> 0
        7 -> 1
        8 -> 2
        9 -> 3
        10 -> 4
        11 -> 5
        12 -> 0

        In perl 0 is false and anything greater than
        zero is true. This is a long winded way of saying
        that every sixth item in the list above will have
        a remainder of 0 when divided by 6. That's what
        the '%' (modulo) operator does.

        ============

        With this information in hand, we can dispense
        with all those counting variables in your script.

        my @values = 1 .. 12;

        print "$values[0]\n";
        foreach my $value ( @values ) {
        print "$value\n" unless $value % 6;
        }

        Prints
        1
        6
        12

        So we can unlink any file unless it's value
        mod 6 is zero.

        unlink $file unless $file_value % 6;

        What happens if you later need every fifth file?

        unlink $file unless $file_value % 5;

        ============

        I'd like to introduce a subroutine here. Subroutines
        often allow programmers to hide the nitty gritty details
        and that's what I want to do here. Getting the value of
        each file involves the use of a regular expression and
        I'd like to use a the subroutine to better document the
        script.

        sub keep {
        # return 1 (true) if we want to keep the file
        # return 0 (false) if we want to delete the file

        my $value = shift;

        # in case a non .tif file gets in there.
        return 1 unless $value =~ /\.tif$/;

        $value =~ s/\D//g;

        return 1 if $value == 1;
        return 1 unless $value % 6;

        return 0;
        }

        Before we run this let's test it.


        my @files = qw|
        foo
        tif001.tif tif002.tif tif003.tif tif004.tif
        tif005.tif tif006.tif tif007.tif tif008.tif
        tif009.tif tif010.tif tif011.tif tif012.tif
        |;

        foreach my $file ( @files ) {
        print "$file\n" if keep( $file );
        }


        Prints
        foo
        tif001.tif
        tif006.tif
        tif012.tif

        =============

        But what about the $end_frame not mentioned in
        the program description, but included in the scripts?

        my $end_frame = 10;

        my @files = qw|
        foo
        tif001.tif tif002.tif tif003.tif tif004.tif
        tif005.tif tif006.tif tif007.tif tif008.tif
        tif009.tif tif010.tif tif011.tif tif012.tif
        |;

        foreach my $file ( @files ) {
        print "$file\n" if keep( $file, $end_frame );
        }

        sub keep {
        # return 1 (true) if we want to keep the file
        # return 0 (false) if we want to delete the file

        my( $value, $max ) = @_;

        return 1 unless $value =~ /\.tif$/;
        $value =~ s/\D//g;

        return 1 if $value == 1 || $value > $max - 1;
        return 1 unless $value % 6;

        return 0;
        }

        Prints
        foo
        tif001.tif
        tif006.tif
        tif010.tif
        tif011.tif
        tif012.tif

        =============

        I leave the details to you, but you shouldn't have
        too much trouble incorporating this into your script.

        foreach my $file ( @files ) {
        unlink $file unless keep( $file, $end_frame );
        }



        HTH,

        Charles K. Clarkson
        --
        Head Bottle Washer,
        Clarkson Energy Homes, Inc.
        Mobile Home Specialists
        254 968-8328
      • Scott Spencer
        Thank you very much for your input, this is so much simplier than the approach I was trying to use! : ) I am curious tho, and I may be totally misreading
        Message 3 of 4 , Apr 22, 2003
        • 0 Attachment
          Thank you very much for your input, this is so much simplier than the
          approach I was trying to use! : ) I am curious tho, and I may be
          totally misreading this, it looks like I need to manually enter the
          filenames into the @files array... Well it is entirely possible to
          have in the upwards of 1000 values in there because (I should have
          mentioned earlier) these tiff files are frames from a video
          capture : ) Is it still possible for me to open a directory handle
          and get the listing from there into my @files variable?

          Thanks again!

          Scott

          --- In perl-beginner@yahoogroups.com, "Charles K. Clarkson"
          <cclarkson@h...> wrote:
          > Scott Spencer <scott@d...> wrote:
          >
          > : I am new to the list.
          >
          > Welcome.
          >
          > : The script will take every sixth numbered frame and
          > : delete those in between, so when you had file001 - 12
          > : you will end up with file 001 and 006 and 0012. I
          > : hope this is clear.
          >
          > You don't mention whether the files will always start
          > in sequence from 001. I made the assumption that they
          > would. You did say they were sequential, so I assumed the
          > saved files would always be 001, 006, 012, 018, etc.
          > You would never, for instance, save files 002, 007, 013,
          > etc.
          >
          > ============
          >
          > Instead of repairing your current script I decided to
          > lay down some basics and start a new one. One of the
          > first items mentioned to beginners is the use of
          > strictures and warnings.
          >
          > #!/usr/bin/perl
          >
          > use strict;
          > use warnings;
          >
          > These two modules will force you to be a little more
          > disciplined in your script writing. Among many other
          > items, there is a need to use the 'my' function when
          > first using a variable.
          >
          > my $value = 12;
          > $value++;
          >
          > If we leave the 'my' function out, we'll get errors
          > on execution.
          >
          > Global symbol "$value" requires explicit package name at aa.pl line
          6.
          > Global symbol "$value" requires explicit package name at aa.pl line
          7.
          > Execution of aa.pl aborted due to compilation errors.
          >
          > ============
          >
          > Variable defined (declared) with 'my' are called
          > "lexical variables". Lexical variables can be undefined
          > to free up memory. If they are defined within a code
          > block, they are automatically undefined when the block
          > ends (unless a reference to them remains).
          >
          > my $value = 12;
          > {
          > my $value = 10;
          > print "$value\n";
          > }
          > print "$value\n";
          >
          >
          > Prints
          >
          > 10
          > 12
          >
          > ============
          >
          > Now let's look at a part of your problem. How do
          > we find every sixth element of a series? First we'll
          > create an array of integers from 1 to 12.
          >
          > my @values = 1 .. 12;
          >
          > Now we'll cycle through them one at a time and
          > print them.
          >
          > foreach my $value ( @values ) {
          > print "$value\n";
          > }
          >
          > Prints
          >
          > 1
          > 2
          > 3
          > 4
          > 5
          > 6
          > 7
          > 8
          > 9
          > 10
          > 11
          > 12
          >
          > Next, we'll change the print to reflect the
          > value and a computed variable. Stick with me here.
          > I'm getting to something. (Really!)
          >
          > printf "%s -> %s\n", $value, $value % 6;
          >
          > Prints
          >
          > 1 -> 1
          > 2 -> 2
          > 3 -> 3
          > 4 -> 4
          > 5 -> 5
          > 6 -> 0
          > 7 -> 1
          > 8 -> 2
          > 9 -> 3
          > 10 -> 4
          > 11 -> 5
          > 12 -> 0
          >
          > In perl 0 is false and anything greater than
          > zero is true. This is a long winded way of saying
          > that every sixth item in the list above will have
          > a remainder of 0 when divided by 6. That's what
          > the '%' (modulo) operator does.
          >
          > ============
          >
          > With this information in hand, we can dispense
          > with all those counting variables in your script.
          >
          > my @values = 1 .. 12;
          >
          > print "$values[0]\n";
          > foreach my $value ( @values ) {
          > print "$value\n" unless $value % 6;
          > }
          >
          > Prints
          > 1
          > 6
          > 12
          >
          > So we can unlink any file unless it's value
          > mod 6 is zero.
          >
          > unlink $file unless $file_value % 6;
          >
          > What happens if you later need every fifth file?
          >
          > unlink $file unless $file_value % 5;
          >
          > ============
          >
          > I'd like to introduce a subroutine here. Subroutines
          > often allow programmers to hide the nitty gritty details
          > and that's what I want to do here. Getting the value of
          > each file involves the use of a regular expression and
          > I'd like to use a the subroutine to better document the
          > script.
          >
          > sub keep {
          > # return 1 (true) if we want to keep the file
          > # return 0 (false) if we want to delete the file
          >
          > my $value = shift;
          >
          > # in case a non .tif file gets in there.
          > return 1 unless $value =~ /\.tif$/;
          >
          > $value =~ s/\D//g;
          >
          > return 1 if $value == 1;
          > return 1 unless $value % 6;
          >
          > return 0;
          > }
          >
          > Before we run this let's test it.
          >
          >
          > my @files = qw|
          > foo
          > tif001.tif tif002.tif tif003.tif tif004.tif
          > tif005.tif tif006.tif tif007.tif tif008.tif
          > tif009.tif tif010.tif tif011.tif tif012.tif
          > |;
          >
          > foreach my $file ( @files ) {
          > print "$file\n" if keep( $file );
          > }
          >
          >
          > Prints
          > foo
          > tif001.tif
          > tif006.tif
          > tif012.tif
          >
          > =============
          >
          > But what about the $end_frame not mentioned in
          > the program description, but included in the scripts?
          >
          > my $end_frame = 10;
          >
          > my @files = qw|
          > foo
          > tif001.tif tif002.tif tif003.tif tif004.tif
          > tif005.tif tif006.tif tif007.tif tif008.tif
          > tif009.tif tif010.tif tif011.tif tif012.tif
          > |;
          >
          > foreach my $file ( @files ) {
          > print "$file\n" if keep( $file, $end_frame );
          > }
          >
          > sub keep {
          > # return 1 (true) if we want to keep the file
          > # return 0 (false) if we want to delete the file
          >
          > my( $value, $max ) = @_;
          >
          > return 1 unless $value =~ /\.tif$/;
          > $value =~ s/\D//g;
          >
          > return 1 if $value == 1 || $value > $max - 1;
          > return 1 unless $value % 6;
          >
          > return 0;
          > }
          >
          > Prints
          > foo
          > tif001.tif
          > tif006.tif
          > tif010.tif
          > tif011.tif
          > tif012.tif
          >
          > =============
          >
          > I leave the details to you, but you shouldn't have
          > too much trouble incorporating this into your script.
          >
          > foreach my $file ( @files ) {
          > unlink $file unless keep( $file, $end_frame );
          > }
          >
          >
          >
          > HTH,
          >
          > Charles K. Clarkson
          > --
          > Head Bottle Washer,
          > Clarkson Energy Homes, Inc.
          > Mobile Home Specialists
          > 254 968-8328
        • Charles K. Clarkson
          ... Without access to your system I needed to simulate a directory structure. This is a useful technique for designing scripts. I assumed you would create the
          Message 4 of 4 , Apr 22, 2003
          • 0 Attachment
            Scott Spencer <scott@...> wrote:

            : Is it still possible for me to open a directory handle
            : and get the listing from there into my @files variable?

            Without access to your system I needed to simulate
            a directory structure. This is a useful technique for
            designing scripts. I assumed you would create the files
            array from a directory of your choosing. 'readdir' is
            excellent for this.

            With so many files, it might be more memory
            efficient to use 'while' rather than 'for'. 'for' pulls
            the entire array into memory, while 'while' reads one
            filename at a time. YMMV.


            opendir DIR, $path or die "Cannot open $path: $!";

            while ( my $file = readdir DIR ) {
            # only process files;
            next unless -f "$path$file";

            print "$file\n" if keep( $file, $end_frame );
            }

            closedir DIR;


            HTH,

            Charles K. Clarkson
            --
            Head Bottle Washer,
            Clarkson Energy Homes, Inc.
            Mobile Home Specialists
            254 968-8328
          Your message has been successfully submitted and would be delivered to recipients shortly.