سؤال

I created a script to exact all tar.gz file it is composed of 5 tar files and the last tar file should remain tar it should not be extracted. So my problem is it will all extract the tar.gz file.

while true; do
    for f in *.tar.gz; do
        case $f in '*.tar.gz') exit 0;; esac
        tar zxf "$f"
        rm -v "$f"
    done
done

What is the correct way to my solve problem?

هل كانت مفيدة؟

المحلول

You say:

I created a script to exact all tar.gz file it is composed of 5 tar files and the last tar file should remain tar it should not be extracted.

I can see two interpretations for that:

  1. There are five files with the .tar.gz extension in a directory. The first four of those files should be extracted and removed; the fifth should be left unextracted.

  2. There is one .tar.gz file which contains 5 .tar files. The first four of those .tar files should be extracted from the .tar.gz; the fifth should be left unextracted.

There are many ways to deal with each scenario. I'm assuming that the tar file names do not contain spaces or newlines or other oddball characters (which is plausible). If you have oddball file names, it is probably simplest to sanitize them first. Amongst other things, these assumptions mean that you could safely use ls output. However, it is still best not to do so. I am going to assume that 5 is a fixed and magic number.

Scenario 1

i=0
for tarfile in *.tar.gz
do
    $(($i++))
    [ $i = 5 ] && break
    tar -xf "$tarfile"
done

This counts the files it extracts, and stops after the count reaches 5 (so it only extracts the first 4 files).

Scenario 2

tarfiles=$(tar -tf *.tar.gz | sed '$d')
tar -xf *.tar.gz $tarfiles

This collects the list of tar files contained inside the compressed tar file, and deletes the last one listed. It then requests tar to extract the remaining files — so the directory will contain the original .tar.gz file and all the files except the last extracted from the .tar.gz file. If the extracted files are tar files, you can then extract those individually:

for tarfile in $tarfiles
do tar -xf "$tarfile"
done

If you want to remove the extracted tar files too, you can do that.

Demo of Scenario 2

$ mkdir junk
$ cp *.c junk
$ cd junk
$ ls
bo.c     zigzag.c
$ for i in {1..5}; do tar -cf tarfile-$i.tar *.c; done
$ ls -l
total 144
-rw-r--r--  1 jleffler  staff    546 May  7 22:34 bo.c
-rw-r--r--  1 jleffler  staff  10752 May  7 22:35 tarfile-1.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-2.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-3.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-4.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-5.tar
-rw-r--r--  1 jleffler  staff   7305 May  7 22:34 zigzag.c
$ tar -czf tarfile-N.tar.gz *.tar
$ ls -l
total 152
-rw-r--r--  1 jleffler  staff    546 May  7 22:34 bo.c
-rw-r--r--  1 jleffler  staff  10752 May  7 22:35 tarfile-1.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-2.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-3.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-4.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-5.tar
-rw-r--r--  1 jleffler  staff   2787 May  7 22:36 tarfile-N.tar.gz
-rw-r--r--  1 jleffler  staff   7305 May  7 22:34 zigzag.c
$ tar -tvf tarfile-N.tar.gz
-rw-r--r--  0 jleffler staff   10752 May  7 22:35 tarfile-1.tar
-rw-r--r--  0 jleffler staff   10752 May  7 22:36 tarfile-2.tar
-rw-r--r--  0 jleffler staff   10752 May  7 22:36 tarfile-3.tar
-rw-r--r--  0 jleffler staff   10752 May  7 22:36 tarfile-4.tar
-rw-r--r--  0 jleffler staff   10752 May  7 22:36 tarfile-5.tar
$ rm *.tar *.c
$ ls -l
total 8
-rw-r--r--  1 jleffler  staff  2787 May  7 22:36 tarfile-N.tar.gz
$ tarfiles=$(tar -tf *.tar.gz | sed '$d')
$ echo $tarfiles
tarfile-1.tar tarfile-2.tar tarfile-3.tar tarfile-4.tar
$ tar -xf *.tar.gz $tarfiles
$ ls -l
total 104
-rw-r--r--  1 jleffler  staff  10752 May  7 22:35 tarfile-1.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-2.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-3.tar
-rw-r--r--  1 jleffler  staff  10752 May  7 22:36 tarfile-4.tar
-rw-r--r--  1 jleffler  staff   2787 May  7 22:36 tarfile-N.tar.gz
$ for file in $tarfiles; do echo $file; tar -tvf $file; rm $file; done
tarfile-1.tar
-rw-r--r--  0 jleffler staff     546 May  7 22:34 bo.c
-rw-r--r--  0 jleffler staff    7305 May  7 22:34 zigzag.c
tarfile-2.tar
-rw-r--r--  0 jleffler staff     546 May  7 22:34 bo.c
-rw-r--r--  0 jleffler staff    7305 May  7 22:34 zigzag.c
tarfile-3.tar
-rw-r--r--  0 jleffler staff     546 May  7 22:34 bo.c
-rw-r--r--  0 jleffler staff    7305 May  7 22:34 zigzag.c
tarfile-4.tar
-rw-r--r--  0 jleffler staff     546 May  7 22:34 bo.c
-rw-r--r--  0 jleffler staff    7305 May  7 22:34 zigzag.c
$ rm -f *
$ cd ..
$ rmdir junk
$

نصائح أخرى

The problem is you are using this command to extract the file:

tar zxf "$f"

And what that does is decompress the gzip file & then extract tar the archive all at once. So all tarred contents would be extracted. Instead, what you want to do is use gzip -d instead:

gzip -d "$f"

That will only decompress the gzip. As for the logic of only extracting the contents of the first four tar archives but not the fifth, it seems like there is more code logic you are not sharing?

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top