in reply to tar_mv: move tar data as it's being extracted

The traditional approach...viva unix...

No tarball other than in the streams...

$ (cd src_dir; tar cvf - .) | (cd target_dir; tar xvf -)

or never change your current directory, but wish to redirect from an existing tarball:

$ (cd tarfile_dir; tar xvf - tarball.tar) | (cd tgt_dir; tar xvf -)
Update:As mem points out below, the second example above is sort of meaningless -- no need for the pipe...this is what I meant:

$ (cd tgt_dir; tar xvf - src_dir/tarball.tar)

In the cases where the tarball already exists, this presumes that the directory paths are relative vs. absolute. (as is pointed out below, you can use -C to redirect absolute paths to relative)

Matt

update: removed redundant first example, functionally nothing more than:

$ cd tgt_dir; tar xvf src_dir/tarball.tar

Because I was thinking of:

$ gunzip -c tarball.tar.gz | (cd tgtdir; tar xvf -)

Replies are listed 'Best First'.
Re: Re: tar_mv: move tar data as it's being extracted
by mem (Acolyte) on Jul 30, 2002 at 07:11 UTC
    $ (cd src_dir; tar cvf - .) | (cd target_dir; tar xvf -)

    Actually that's not what the original monk wants to do. Brother blyman wants to extract files inside a tar archive to a different location than the one they use inside the archive. For example, the archive contains /usr/bin/perl and he wants to be able to extract it to /usr/local/bin/perl. Your second example:

    $ (cd tarfile_dir; tar xvf - tarball.tar) | (cd tgt_dir; tar xvf -)

    Doesn't do much, because it extracts tarball.tar from a tar archive coming via STDIN, and the second tar does nothing.

    Besides the problem already pointed out by Brothen blyman, I think there's a second one: permissions for directories are not preserved. If want to extract /usr/bin/perl to /usr/local/bin/perl, you'd like to preserve the permissions of at least bin. Inside the tarball there could be files as well as other little beasts, such as directories, fifos and devices. I was trying to come up with a solution that doesn't involve a temporary storage location but everything I've come up with has drawbacks (performance being the most common one). Looking at Archive::Tar, you can get a list of the files in the tar archive and then request the data for each of them. In principle you'll be doing something like:

    my @files = $archive->get_files; foreach my $file (@files) { my $dst = compute_new($orig, $replacement, $file); save_data($file, $dst); }

    The problem is of course what I have pointed out, namely getting the permissions right. save_data here of course handles permissions and all the little details. What I wanted to make clear is that this requires you to read the tarfile twice: once for the list of files and a second one for the actual data. A forward iterator kind of interface would be helpful here. You would just get the name of the current file and request its data if needed or just skip to the next file. That would allow for a solution that works with pipes.

      Actually that's not what the original monk wants to do. Brother blyman wants to extract files inside a tar archive to a different location than the one they use inside the archive.

      Correct - I wasn't able to explain it so succinctly, though, and didn't provide any examples of what I meant. Thanks for reading my code (and mind!) to figure out what problem I was trying to solve :)

      Besides the problem already pointed out by Brother blyman, I think there's a second one: permissions (and ownership) for directories (and files) are not preserved.

      Yep, I did some monkeying around and realized that my program wasn't getting that info, so couldn't possibly do anything with it.

      I believe that the original problem can be solved with a one-pass program because the intent is to extract all files to a different root directory; a future enhancement would be to extract only selected files to some arbitrary directory.

      I ++'ed you for a great reply; it's gotten me thinking in new directions, so thanks.

      blyman
      setenv EXINIT 'set noai ts=2'