Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Yet Another Tar-Gzip File Expander

by straywalrus (Friar)
on May 13, 2002 at 21:53 UTC ( [id://166309]=CUFP: print w/replies, xml ) Need Help??

Yet another *.tar.gz && *.tgz file expander. Yeah, I know this is probably an overused theme, but I needed to write one for my machines, so here is my version.
#!/usr/bin/perl -w $|++; use strict; my (@list, $d, $i); die "Need Directory Param!\n" unless $ARGV[0]; my $cmd = qq/tar -zxvf/; opendir LOCAL,$ARGV[0]; @list = readdir LOCAL; foreach $d (0..$#list) { if($list[$d] =~ /.+\.tar\.gz/) { qx/$cmd $list[$d]/; $i++; } elsif($list[$d] =~ /.+\.tgz/) { qx/$cmd $list[$d]/; $i++; } } print "$i files expanded!\n"; closedir LOCAL;

Replies are listed 'Best First'.
Re: Yet Another Tar-Gzip File Expander
by thelenm (Vicar) on May 13, 2002 at 22:22 UTC
    A couple of things I notice...
    • If you pass a directory other than the current directory, the script will be unable to find the tar file.
    • The code inside your if/elsif is the same, so you can reduce it to a single if test.
    • It would be more intuitive to use @list in the foreach loop, instead of using 0..$#list and an index variable. Actually, a while loop might be better, especially if there are many files in the subdirectory. That way you won't have to read the entire list into memory.
    • The actual call to tar is insecure. For example, someone might name a file "; rm -rf /; .tar.gz", and if root runs this script over that directory, your filesystem will be hosed. Avoid calling the shell by giving multiple arguments to system.
    I might rewrite the code like this:
    #!/usr/bin/perl -w $|++; use strict; my $total=0; my $dir = shift || die "Needs Directory Param!\n"; opendir LOCAL,$dir or die "Can't open directory '$dir': $!\n"; while (my $file = readdir LOCAL) { next unless $file =~ /\.t(?:ar\.)?gz\z/; system("tar", "xzvf", "$dir/$file"); $total++; } closedir LOCAL; print "$total files expanded!\n";
    Update: fixed a typo as pointed out by straywalrus.
      I took your code and down loaded it, then I realized a few things:

      A) you left out the first brace on the line
      next unless $file =~ /\.t(?:ar\.)?gz\z/); # it should be next unless ($file =~ /\.t(?:ar\.)?gz\z/);
      That was not meant to flame you, just to point it out for others who read this.

      <ident>B) Your script runs into the same flaw as mine: It expands the archives in the CWD. I read the manual on tar, but it was older than tar, so the option I thought should work didn't. Really all I think I need to do is to change the current working directory to whatever $ARGV[0] is at the time. That should solve it. Thanx again for the regex compression. i re-wrote mine as this:
      #!/usr/bin/perl -w $|++; use strict; my (@list, $d, $i); die "Need Directory Param!\n" unless $ARGV[0]; my $cmd = qq/tar -zxvf /; opendir LOCAL,$ARGV[0] || die "Cannot Open dir $ARGV[0]"; @list = readdir LOCAL; foreach $d (0..$#list) { if($list[$d] =~ /.+\.t?(ar\.)?gz/) { qx/$cmd $ARGV[0]\/$list[$d]/; $i++; } } print "$i files expanded!\n"; closedir LOCAL;
      Of Course this is still a few lines larger than yours, but you see, this is my code and I kept it how i originally wrote it. No offense to you, but that is your code. Besides the fact that I did not explain my whole purpose in writing this program. I am going to expand this and need to have the directory read into an array for later use. Thanx again.

      <straywalrus>

        I would prefer the system() over the qx//. Apart from being more secure, you can test whether the command was successful. At the moment, you are using qx// in void context : capturing the output of the command and ingoring it. This is a waste of memory and CPU cycles.

        I'd write it thus:

        { system("tar", "zxvf", $ARGV[0] . "/$list[$d]") == 0 or print STDERR "Error running tar zxvf on $list[$d]"; $i++; }

        my €0.02

        Thanks for the correction. My code is untested, as you can clearly see. I hope you didn't take my criticisms as flames; publicly-posted code is meant to be scrutinized so that it can be improved. I have more to learn than most people when it comes to improving my code, anyway. :-)

        Oh, as far as the tar command only untar/zipping files in the current directory, you can change your current directory to the appropriate subdirectory by using the chdir command.

      The security issue is not such a big issue, because this is on a stand alone Linux Box, but all the other issues will be changed. Thank you for reminding me that I need to check whether or not the directory opened correctly and thank you for the good use of compression.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://166309]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (6)
As of 2024-03-29 11:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found