Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

untarring number of files

by agent (Acolyte)
on Oct 22, 2003 at 16:26 UTC ( [id://301270]=perlquestion: print w/replies, xml ) Need Help??

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

I am trying to untar a number of files in a directory..wrote this script but does not work..any tips ?
#!/usr/bin/perl @list=`ls *.tar`; foreach $file(@list) { chomp ($file); system('tar -xvf $file'); }

Replies are listed 'Best First'.
Re: untarring number of files
by gjb (Vicar) on Oct 22, 2003 at 16:48 UTC

    The string that you supply to system as an parameter is in single quotes. That means no interpolation of variables is done, hence you're always trying to untar the file with name '$file', regardless of the value that variable holds in the foreach.

    Using double quotes might solve your problem if nothing else goes wrong along the way. You might want to look at the other answers to your question for better approaches.

    Hope this helps, -gjb-

      thanks gjb ..converting to double quotes worked .. Appreciate all the other replies too.!!
Re: untarring number of files
by hardburn (Abbot) on Oct 22, 2003 at 16:38 UTC

    What error message do you get? We need more specifics to help you.

    Also, you can change your call to ls to use Perl's globbing operator instead:

    @list = <*.tar>;

    And you can use Archive::Tar instead of calling tar:

    foreach $file (@list) { use Archive::Tar; $tar = Archive::Tar->new; $tar->read( $file ); $tar->extract(); }

    Pure Perl solutions are generally faster and safer than calling external programs, though perhaps a bit longer in some cases.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    :(){ :|:&};:

    Note: All code is untested, unless otherwise stated

Re: untarring number of files
by talexb (Chancellor) on Oct 22, 2003 at 16:43 UTC

    Alternatively, a one-liner:

    perl -e 'while(<*.tar>){`tar -xvf $_`;}'

    --t. alex
    Life is short: get busy!
Re: untarring number of files
by dragonchild (Archbishop) on Oct 22, 2003 at 17:23 UTC
    Why are you using Perl?
    #!/bin/sh for file $(ls -1 *.tar) do tar xvf $file done
    Or, from the command line ...
    ls -1 *.tar | xargs tar xvf

    ------
    We are the carpenters and bricklayers of the Information Age.

    The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

    ... strings and arrays will suffice. As they are easily available as native data types in any sane language, ... - blokhead, speaking on evolutionary algorithms

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      Why are you using Perl?

      Maybe he was just sticking with what he knows... and trying to write portable code.

      for file $(ls -1 *.tar)

      First, the error: you need for file in. Secondly, that has portability issues. $( ) works with some Bourne-like shells, such as bash and ksh, but it isn't ubiquitous. You could probably get away with for file in `ls -1 *.tar` but there is really no reason that I know of not to just use a glob like for file in *.tar instead.

      -sauoq
      "My two cents aren't worth a dime.";
      
        Perhaps I'm missing something as well, but having the for loop iterate over the results of 'ls -l' doesn't seem like it'd work, as it would try to untar things like '-rw-rw-r--' and 'Oct'. Perhaps 'ls' would be more appropriate. Heck, you could even leave the external program out of it.
        for file in *tar; do tar xvf $file; done

        thor

        Update:Yeah, I'm an idiot. "ell-ess dash ell" ne "ell-ess dash one". *shrugs*
Re: untarring number of files
by sweetblood (Prior) on Oct 22, 2003 at 17:39 UTC
    What your doing here is essentially a shell script with a Perl wrapping. I can appreciate that in the beginning you might be tempted to do this. But if this is what your going to do you may as well leave Perl out of it. If you have an immeadiate, one time need to untar a group of files you may be better off just using shell, but if you truly want to use Perl because it's called for then think about the best practices to implement your needs. Perl is a great tool for doing all kinds of programming, whether it's a system task or database system or whatever but you shouldn't go out of your way to do it in Perl, especially if your going to just do `` and system calls. In this example that's already been pointed out you could use Archive::Tar and that would be usefull if your application was doing more than just untaring, and certainly if this is a practice script to get your feet wet with Perl it's a good way to go. But if your really just trying to get your work done I'd suggest using the most pratical tool for the job. Perl one-liners, shell scripts, c, c++ whatever is best. You might be able to get a screw out using a circular saw but it may be a little overkill.

    Good luck and come back often as you move up the learning curve. The Perlmonks is a great resource!

      ...I don't get the "why use Perl for this" attitude. Did anyone consider that this might have been an extract from a much larger Perl program?

      And there's no good reason *not* to use Perl for this. Frankly, using Perl is just about the same as using a shell script. An interpreter must be invoked. And although Perl may weigh more than the chosen shell for a script, it's not much heavier.

      Not to mention, as someone else pointed out, that if you solve it with a Perl script, you can take that to a number of other platforms.

      ...All the world looks like -well- all the world, when your hammer is Perl.
      ---v

      I disagree with considering "Perl wrapping" as over-engineering. In my expirience if I have 2 or 3 lines of command line tasks that I do regularly I find it quite convenient to 'wrap' them in Perl. Why Perl you may ask? Primarily to avoid shell differences. I have found many of these full blown 3 line Perl scripts ( complete with -w and use strict ) often grow in functionality and are huge time savers. More often than not the fact that I can jump on a server and complete these task in one command does more for my image than the real 'meaty' tasks I accomplish. Additionaly I can easily add on some of my home brew modules that take care of cross-platform issues ( Like ls vrs dir and / vrs \ ). I also get the added bonus of keeping my Perl coding speed and familiarity brushed up.

Re: untarring number of files
by waswas-fng (Curate) on Oct 22, 2003 at 18:48 UTC
    or form the comand line with no perl:
    ls *.tar |xargs -l1 -i tar -xvf "{}"
    that is dash-ell-one space dash-eye.


    -Waswas
Re: untarring number of files
by Plankton (Vicar) on Oct 22, 2003 at 18:55 UTC
    $ find . -name '*tar' -exec tar -xvf {} \;

    Plankton: 1% Evil, 99% Hot Gas.
      Yup, but be careful of uncontrolled directory recursion there. If there were subdirectories containing tar files (or even a directory named, say "guitar"), you'd get results you wouldn't expect. Gnu find's maxdepth option is your friend.

      Using find and xargs without the Gnu -print0 and -0 options is getting perilous these days. Users just don't understand that, although you can put a space in a file name, you don't want to.

      xargs is also not guaranteed to operate on the entire expanded glob in one shot, calling several instances of the required command if there are more than (typically) 1024 arguments.

      So maybe using Perl for this isn't such a bad idea after all.

      --
      bowling trophy thieves, die!

Re: untarring number of files
by Roger (Parson) on Oct 23, 2003 at 03:21 UTC
    Your script doesn't work because you are using single quotes inside system(...), and perl will not expand variables inside single quotes. Change single quotes to double quotes and it will work -

    #!/usr/bin/perl -w chomp(my @list=`ls *.tar`); foreach (@list) { system "tar -xvf $_"; }
    Note that you don't have to untar a single file at a time, tar is quite happy to accept multiple files at the same time:
    #!/usr/bin/perl -w chomp(my @list=`ls *.tar`); system "tar -xvf " . qq{@{[@list]}};
    And better still, you don't even need to write a script at all, just type this at the shell prompt:
    tar -xvf *.tar
    Update: Thanks to sauoq for pointing out my mistake with tar and multiple input files.
      Note that you don't have to untar a single file at a time, tar is quite happy to accept multiple files at the same time:

      Uhm... no.

      Arguments after the tarball filename are expected to be files to untar from the tarball. So, that won't work at all. Instead, you'll get an error like "foo.tar: Not found in archive."

      -sauoq
      "My two cents aren't worth a dime.";
      
Re: untarring number of files
by zakzebrowski (Curate) on Oct 23, 2003 at 12:18 UTC
    Try something, completly different...
    If you don't understand this, do a perldoc File::Find
    use File::Find; find (\&doSomething,'.'); # Find stuff in curr dir, execute subroutine + do something on match. (\&[name] is a subroutine pointer... ) exit(0); # not needed sub doSomething{ my $fn = $_; # also not needed but makes life easy if ((!(-d $fn)) && ($fn =~/tar$/i)){ # -d test not really necessary system("tar","-xvf",$fn); # May want to do a which tar if it doesn +'t work ... } }
    Caveat: Untested.


    ----
    Zak
    undef$/;$mmm="J\nutsu\nutss\nuts\nutst\nuts A\nutsn\nutso\nutst\nutsh\ +nutse\nutsr\nuts P\nutse\nutsr\nutsl\nuts H\nutsa\nutsc\nutsk\nutse\n +utsr\nuts";open($DOH,"<",\$mmm);$_=$forbbiden=<$DOH>;s/\nuts//g;print +;
Re: untarring number of files
by Anonymous Monk on Oct 24, 2003 at 04:45 UTC
    Any line similar to

    system('tar -xvf $file');

    should quote the filename:

    system(qq(tar -xvf "$file"));

    to protect against spaces. This is not perfect; it doesn't protect against doublequotes in the filename.

Re: untarring number of files
by pizza_milkshake (Monk) on Oct 24, 2003 at 07:17 UTC
    perl -le'`tar -zxvf "$_"` for <**/*.tar.gz>'
    perl -e'$|=@a=qw /; for(;;){$n=abs 49-$c%98; \ printf"%-49s", $a$c++%4x$n; select $|,$|,$|,.1; \ print"\010"x49}'
Re: untarring number of files
by talexb (Chancellor) on Oct 22, 2003 at 16:30 UTC

    Yeah, try the Perl debugger.

    --t. alex
    Life is short: get busy!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://301270]
Approved by gjb
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (4)
As of 2024-03-28 23:26 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found