Alex Ardin wrote:
Hi,

Hello,

I frequently have to review logs that are captured with 'script' using
terminal but these logs have many control characters.

The intent of the script is the following:

1. Get a listing of all the logs in a directory, storing the list of
files in an array.

perldoc -f opendir
perldoc -f readdir
perldoc -f glob


2. For each filename in the array, create a new filename but append a
".x" to the original filename, so that file 'a' would result in a new
file 'a.x', as an example.
3. Open the original file, search and remove any control characters
(such as  ^M, ^C, and so on) line by line and store the results in the
newly created file ending in .x (such as the a.x example above).
4. After reaching the end file, close both files.
5. Move the newly created .x file so that it replaces the original
file (or 'mv a.x a' in the example above).

What happens is that the script works fine, all control characters are
replaced in the file, but the move fails, so that if I start with a
directory containing these files:

xong$ ls -rlt
-rw-r--r--  1 rootroot  staff  50033 Oct 11 17:43 xyz
-rw-r--r--  1 rootroot  staff  50033 Oct 13 18:57 123

when the script finishes executing, I end up with these file, the
first two are the original files with all the control characters, the
last two are the newly created files with the control characters
removed:

xong$ ls -rlt
-rw-r--r--  1 rootroot  staff  50033 Oct 11 17:43 xyz
-rw-r--r--  1 rootroot  staff  50033 Oct 13 18:57 123
-rw-r--r--  1 rootroot  staff  49792 Jan  4 22:14 xyz?.x
-rw-r--r--  1 rootroot  staff  49792 Jan  4 22:14 123?.x

The question mark after the file name means that you haven't removed the newline character.


Here's the errors I see when the script executes, the comments are
just for debugging:

Here's a listing of the files:
123
xyz

Here's newfile: 123
.xHere's oldfile: 123

There you can see the newline between '123' and '.x'


Now mv file
Here's newfile: 123
.xHere's oldfile: 123

And again there.


usage: mv [-f | -i | -n] [-v] source target
        mv [-f | -i | -n] [-v] source ... directory
sh: line 1: .x: command not found

And the shell (sh) outputs an error message because of the newline.


I'm not sure why this is happening, the newfile should contain "123.x"
but instead the .x is appearing on the newline.  I've gone through the
"Programming Perl" book and can't seem to fine another way to do this,
and I've also searched this group, and didn't find anything similar.

Here's the script:

#!/usr/bin/perl

#
# Delete all control characters in a group of files in a directory.
#

#use strict;
use warnings;

if ($#ARGV != 0) {
     print "\nusage: get_file_list.pl directory\n\n";
     exit;
}

$dir_path = $ARGV[0];
chdir "$dir_path" or die "\ncd failed, check file path!\n\n";

$cmd = "pwd";
if(system($cmd)) { print "\n\npwd failed.\n"; }

$cmd = "ls -l";
if(system($cmd)) { print "\n\nFile listing failed.\n"; }

# Store file listing in a array:
$cmd = "ls";
my @fl = qx($cmd);

In list context (like you are using above) the qx// operator returns lines of text with each line ending with a newline.

You could use chomp() to remove the newlines or just use perl's built-in functions for reading directory entries.


print "\nHere's a listing of the files:\n";

foreach $file (@fl) {
         print $file;
}

I thought it was a result of my foreach loop but the loop exits after
the last file is reached, so there's nothing to force a newline when
my script copies the original filename to a new file name ending in
".x".

foreach $file (@fl) {
        $oldfile = $file;
        my $newfile = $oldfile . ".x";
        print("Here's newfile: $newfile");
        print("Here's oldfile: $oldfile");

        open(OF, $oldfile);
        open(NF, ">$newfile");

You should _always_ verify that open() worked correctly before trying to use a possibly invalid filehandle.


        # read in each line of the file
        while ($line =<OF>) {
                $line =~ s/\cM//g;
                $line =~ s/\cH//g;
                $line =~ s/\cC//g;
                $line =~ s/\cL//g;
                $line =~ s/\cG//g;
                $line =~ s/\cP//g;
                $line =~ s/\cQ//g;
                $line =~ s/\cR//g;
                $line =~ s/\c[//g;
                print NF $line;
        }

        print("\nNow mv file\n");
        print("Here's newfile2: $newfile");
        print("Here's oldfile2: $oldfile");

        $cmd = "mv $newfile $oldfile";
        if(system($cmd)) { print "rename failed\n"; }

You should probably just use perl's built-in rename() function.

perldoc -f rename


        close(OF);
        close(NF);
}

I also thought it had been the result of my closing my files after I
attempted the move, but I get the same results if I move these lines:

        close(OF);
        close(NF);

above this line:

print("\nNow mv file\n");

so that the files are closed and then attempt to move them.

Is it possible to understand how to work around this?


Here is another way to do that (UNTESTED):

#!/usr/bin/perl
#
# Delete all control characters in a group of files in a directory.
#

use strict;
use warnings;

if ( @ARGV != 1 ) {
    print "\nusage: get_file_list.pl directory\n\n";
    exit 1;
}

my $dir_path = $ARGV[ 0 ];
chdir $dir_path or die "\ncd failed, check file path!\n\n";

opendir my $DIR, '.' or die "Cannot opendir because: $!";

my @fl = grep -f, readdir $DIR;

foreach my $file ( @fl ) {
    my $oldfile = $file;
    my $newfile = $oldfile . ".x";
    print "Here's newfile: $newfile";
    print "Here's oldfile: $oldfile";

    open OF, '<', $oldfile or die "Cannot open '$oldfile' because: $!";
    open NF, '>', $newfile or die "Cannot open '$newfile' because: $!";

    # read in each line of the file
    while ( <OF> ) {
        tr/\cM\cH\cC\cL\cG\cP\cQ\cR\c[//d;
        print NF;
    }

    print "\nNow mv file\n";
    print "Here's newfile2: $newfile";
    print "Here's oldfile2: $oldfile";

rename $newfile, $oldfile or die "Cannot rename $newfile to $oldfile because: $!";

    close OF;
    close NF;
}

__END__


John
--
Any intelligent fool can make things bigger and
more complex... It takes a touch of genius -
and a lot of courage to move in the opposite
direction.                   -- Albert Einstein

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to