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

Hi All,

I have a simple problem, hope monks will give me a solution.Problem is like this.I have some lines in a file. They are all dir paths.I should iterate through each and if i found a file say *END*.txt inside that dir, i should delete the entry in that file, if not continue to find, I have used Arrays for this. But my code is giving infinite loop. Please help me out of this.

open(FD,"FILE_LAST_MOD_DIR") or die $!; my @array_LAST_MOD_FILE=<FF>; close(FD); #While length of array not eq 0 while(@array_LAST_MOD_FILE != 0) { for($arr=0;$arr<@array_LAST_MOD_FILE;$arr++) { chomp($array_LAST_MOD_FILE[$arr]); print "ARRAY ELEMENT in $arr position |$array_LAST_MOD +_FILE[$arr]| \n"; my @arr_find=`find $array_LAST_MOD_FILE[$arr] -iname * +END*.txt -type f`; my $length_of_array=@arr_find; print "LENGTH OF THE ARRAY=$length_of_array|\n"; #If Length is 0 means, file not yet created, go to next path if($length_of_array eq 0) { next; } else { #You got END file, delete the entry from FILE as well as A +rray delete $array_LAST_MOD_FILE[$arr]; open(FD,">>FILE_LAT_MOD_DIR") or die $!; foreach my $i (@array_LAST_MOD_FILE) { print FD"$i\n"; } close(FD); }#End If }#End For }#End While

Please let me know where i am doing mistake.

Thanks,
ShekarKCB.

Replies are listed 'Best First'.
Re: Manipulating Arrays
by Corion (Patriarch) on Jun 12, 2009 at 07:49 UTC

    I don't understand what your code is trying to do, neither from your code nor from your description. Can you please look at the following list and expand it so we have a common understanding of what the code is supposed to do?

    1. Read file FILE_LAST_MOD_DIR to get a list of directories to look in
    2. While we have directories in that list do:
      1. For each directory, look if there is a file with the name matching *END*.txt
      2. If such a file exists, remove that file from the FILE_LAST_MOD_DIR and our list.

    If the above description is correct, then consider using Tie::File to treat a line-oriented file just like an array. For removing files, see unlink, not delete. You will also likely want to use the File::Glob::bsd_glob function instead of the find program.

    For your coding style, please don't use C-style for loops. They are almost always an error. It's better to use the foreach-style of loops.

    You haven't told us what the output of your program is and where it enters into an infinite loop. If you would provide a self-contained example that does not rely on a specific directory structure and specific files, that would help us replicate your problem and then we could help you better with your concrete problem.

      Hi Corion,

      Thanks for reply. Yes i will use foreach loop.My input is a file with all the entries, for eg:

      /home/shekarkcb/abc/ /home/shekarkcb/def/ /home/shekarkcb/abc/
      I got to do these things

      1)Read Each entry from file, go to that folder, find *END*txt. if found then delete a entry from file.
      2)If not found then do a next till finds *END*txt.

      I have used Arrays for these.
      -> First open file, put all entry in an array.
      -> while array (@array_LAST_MOD_FILE) length not equals to 0, for each of that entry (used c style for loop as you mentioned) i.e for each directory used find to 'find' the file *END*txt, and stored result in an array.
      -> Again checking the length of it is 0 means no result obtained (no END file),
      if not 0 then yes got END file inside that directory so delete the entry from @array_LAST_MOD_FILE,

      Here is what the problem, i will delete the entry here, but outer while still has the entry.so it is going to infinite. Hope now you got the problem. Please suggest me a soln or a better way to do this.

      Thanks,ShekarKCB

        Tie::File will solve your problem of keeping a file and an array in sync. But you could also just write out the new array at the end of your program, instead of rewriting the file every time. delete does not what you think it does.

        If you're waiting for a file *END*.txt to appear, you should sleep to give the other program some CPU to do its work.

        I'm not sure why or where you have an inner and an outer @array_LAST_MOD_FILE, but I think the main problem of your loop is that delete does not do what you think it does. Removing elements from a list while iterating over that list is always problematic, so I would avoid that in your place and instead create a new list of things to keep, and at the end replace the old list with the new list. This approach works with both, the C-style loop and the foreach-style.

Re: Manipulating Arrays
by afoken (Chancellor) on Jun 12, 2009 at 07:55 UTC

    Missing use strict;, missing use warnings, @array_LAST_MOD_FILE reads from handle FF inside open and close for handle FD.

    Alexander

    --
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)