Your program is frankly a bit of a mess. You seem to be trying things in the hope that they work but without any real reasoning.
I have refactored your code to do what I think you want below. Here are the main changes I have made
-
You must always add
use strict
anduse warnings
to every Perl program you write, and declare all your variables withmy
as close as possible to their first point of use. Those simple measures alone will save you from a lot of simple errors that you will otherwise overlook -
You don’t need
Tie::Array
orCwd
. They are irrelevant to this program -
Your
tie
statement needs a string as the second parameter, so you need to use'Tie::File'
instead ofTie::File
-
Your output file
Trace.txt
will be found by the<*.txt>
glob, so unless you take measures to specifically exclude it your program will copy trim the first and last lines and copy the contents of that file to itself. In my program I have simply checked in thefor
loop whether the current file name isTrace.txt
and skipped it if so -
There is no point in accumulating the data in a buffer
$buff
. You may as well just write the data to the file as you encounter it -
The lines in the tied array
@lines
have no trailing newline, so you will presumably want to add one when you write to the file -
As has been discussed in the comments, you are using
Tie::FILE
andTIE::File
as well as the correctTie::File
. And you have writtenuse Tie::File
(and its variations) four times in total. Sure it doesn’t stop the program from working, but it is a major indication of foggy thinking, and that you are just statements around in the hope that they make your program work -
Using
delete
on anything other than the last element of an array just sets that element toundef
: it doesn’t delete it, and all that happens in the tied file is that the text is removed leaving just a newline. You need to usesplice
instead -
Separating your files into the first, the last, and the rest is unnecessary and makes your code illegible. In my program below I have used a single loop that removes the first line of the file unless it’s the first fil, and removes the last line of the file unless it’s the last file. It’s far easier to read that way
-
Lastly, I’m not at all sure that you want to remove the first and last lines from the existing files, or if you just want all the data copied to your output file except those lines. I have written my program according to your specification, but bear in mind that the files will get shorter by two lines every time you run it, and that probably isn’t the effect you want. If you have a different requirement and can’t see how to modify the code to achieve it then please ask another question.
I hope this helps you.
use strict;
use warnings;
use Tie::File;
my @files = grep -f, glob '*.txt';
my $all_filename="Trace.txt";
open my $out_fh, '>', $all_filename or die qq{Unable to open "$all_filename" for output: $!};
for my $i ( 0 .. $#files ) {
my $file = $files[$i];
next if $file eq $all_filename;
print "Opening $file\n";
tie my @lines, 'Tie::File', $file or die qq{Can't update "$file": $!};
splice @lines, 0, 1 unless $i == 0;
splice @lines, -1, 1 unless $i == $#files;
print $out_fh "$_\n" for @lines;
}
close $out_fh;
1
solved Perl Script can’t use Tie::File