extract file using bash in one tar file but composed of many tar files inside - linux

I have created a script below and when I execute it, I face a problem. Instead to extract it 5 times it will just extract once. So how to get this issue resolved?
i=0
for tarfile in *.tar.gz;
do
((i++))
[ $i = 5 ] && break ;
tar -xzvf $tarfile
done
rm -rvf $tarfile
Help is greatly appreciated. I want to extract the tar.gz file and inside of it is only tar.gz file. Noted: it is decompressed 5 times and I want to get the last tar.gz file decompressed. Please help me.

If and only if the filenames for each of the nested tar do not collide, you can do the following.
for i in `seq 1 4`; do name=$(ls *.tar.gz); tar xvfz $name; rm $name; done;
If they are all the same, like foo.tar.gz inside foo.tar.gz inside foo.tar.gz, you can simply delete the rm $name from the above.
If there are only some collisions you will have to play more clever tricks, such as moving intermediate files into another directory.
Update: If you just want to move the final tar to a new directory, just do use mv after the loop above.
mv *.tar.gz OtherDirectoryName

Related

I am working in linux and have tot extract archives that were already in an archive. Could anyone explain how to extract this while using loops?

#!/bin/bash
tar -xvf assignment_UA_InleidingProgrammeren_Huistaak1-HelloWorld_2019-11-11.tgz
a=$(echo assignment_UA_InleidingProgrammeren_Huistaak1-HelloWorld_2019-11-11.tgz | cut -b 15-35)
b=$(echo assignment_UA_InleidingProgrammeren_Huistaak1-HelloWorld_2019-11-11.tgz | cut -b 37-56)
#cutcommand van geeksforgeeks.org
mkdir -p "$a"/"$b"
mv assignment_UA_InleidingProgrammeren_Huistaak1-HelloWorld_2019-11-11/*.tgz InleidingProgrammeren/Huistaak1-HelloWorld
rmdir assignment_UA_InleidingProgrammeren_Huistaak1-HelloWorld_2019-11-11
for x in InleidingProgrammeren/Huistaak1-HelloWorld
I have already extracted the first archive but i have to extract tthe tgz archives that are in this archive without using hardcode.
I have tried using different loops but it doesn't work and i don't know if i am using them correctly.
Assumptions:
you have an archive, a.tgz, containing some files.
you have an archive, b.tgz, containing some files.
both a.tgz and b.tgz are themselves contained in another archive, top.tgz.
both a.tgz and b.tgz do not exist outside top.tgz when the script starts.
t.tgz
    - a.tgz
         - some files
    - b.tgz
         - some files
Script:
#!/bin/bash
tar -xzf top.tgz
rm -f top.tgz
for F in *.tgz
do
tar -xzf "$F"
rm -f "$F"
done
Extract the top archive first.
Delete that top archive (or move it somewhere else) so the for F in *.tgz does not process it again.
Then loop on the new archives and extract them.
Final result, all files from a.tgz and b.tgz are available.

How to get stdout of tar command

I am trying to tar a file and get it's output store in a variable.
I tried this but it is not working:
resulting_tar=$(tar -zcf "$(date '+%Y-%m-%d').tar.gz" folder)
Any idea how do I go about it?
By default, tar does not report the name of the file created. In fact, it doesn't say anything unless you tell it to, and the options given don't tell it to say anything.
Note that tar doesn't tell you what file it created. You tell tar what file to create.
You'll need to capture the name of the file in a variable and report it yourself:
file="$(date '+%Y-%m-%d').tar.gz"
tar -czf "$file" folder
echo "$file"
Try running tar -czf /dev/null folder; you won't see anything from (most implementations of) tar — and that's not because I specified /dev/null. Specify a name if you prefer: tar -czf junk.tar.gz folder and watch the (lack of) output — and remember to remove junk.tar.gz.
You might want to think about including the folder name in the tar file name, too.
folder="…whatever…"
file="$folder-$(date +'%Y-%m-%d').tar.gz"
tar -czf "$file" "$folder"
echo "$file"
EDIT: No longer applicable after further clarification. Leaving for posterity.
You're likely looking for both stdout and stderr. You can combine the two output streams by appending 2>&1 to your command:
resulting_tar=$(tar -zcf "$(date '+%Y-%m-%d').tar.gz" folder 2>&1)

Execute multiple commands on target files from find command

Let's say I have a bunch of *.tar.gz files located in a hierarchy of folders. What would be a good way to find those files, and then execute multiple commands on it.
I know if I just need to execute one command on the target file, I can use something like this:
$ find . -name "*.tar.gz" -exec tar xvzf {} \;
But what if I need to execute multiple commands on the target file? Must I write a bash script here, or is there any simpler way?
Samples of commands that need to be executed a A.tar.gz file:
$ tar xvzf A.tar.gz # assume it untars to folder logs
$ mv logs logs_A
$ rm A.tar.gz
Here's what works for me (thanks to Etan Reisner suggestions)
#!/bin/bash # the target folder (to search for tar.gz files) is parsed from command line
find $1 -name "*.tar.gz" -print0 | while IFS= read -r -d '' file; do # this does the magic of getting each tar.gz file and assign to shell variable `file`
echo $file # then we can do everything with the `file` variable
tar xvzf $file
# mv untar_folder $file.suffix # untar_folder is the name of folder after untar
rm $file
done
As suggested, the array way is unsafe if file name contained space(s), and also doesn't seem to work properly in this case.
Writing a shell script is probably easiest. Take a look at sh for loops. You could use the output of a find command in an array, and then loop over that array to perform a set of commands on each element.
For example,
arr=( $(find . -name "*.tar.gz" -print0) )
for i in "${arr[#]}"; do
# $i now holds each of the filenames output by find
tar xvzf $i
mv $i $i.suffix
rm $i
# etc., etc.
done

Extracting a .tar file and creating a filelist

i have this little code here
for file in *.tar.gz;
do tar xzvf "${file}" && rm "${file}";
done
It extracts a tar.gz and deletes it. Now I have to create a filelist file (.fl) named like a substring from the .tar . For example, I have to delete the first 5 letters and the last 5 (the extension) from the name of the .tar.gz . And that for every .tar.gz that I extract.
Example:
I have a ABC_A.tar.gz with a ABC_A.xml in it.
I have to make a A.fl
and in that A.fl i have to write ABC_A.xml
Thanks in advance.
In your loop, you can do the following for each file:
# delete first five characters
name=${file:5}
# delete .tar.gz suffix
name=${file%%.tar.gz}
Use
for file in *.tar.gz
do
# this creates the file list into a .fl file:
tar tfz "${file}" > "${file:5:-5}.fl"
# this extracts and afterwards removes the tar archive:
tar xzvf "${file}" && rm "${file}"
done
You also can combine the two in one step:
for file in *.tar.gz
do
tar xzvf "${file}" > "${file:5:-5}.fl" && rm "${file}"
done

Having trouble compressing a file in a different directory

Okay so essentially what I'm doing, is I'm taking all the directories inside of the /servers/ folder, and moving them to a secondary hard drive mounted at /media/backupdrive/. This script is ran once a day, so it makes the directory with the name of the date, and should copy the folders directly over there (The reason I have to do it this way is because my client has limited disk space on his main hard drive and his worlds are upwards of 6-7gb each). Anyway, I can get them to copy the folders to /media/backupdrive/currentdate, but then when I try to compress it, it says it can't compress an empty directory or something along the lines of that.
Here's the code:
#!bin/bash
folderName=$(date +"%m-%d-%y")
mkdir "/media/backupdrive/$folderName"
for i in servers/*; do
cp -rf $i /media/backupdrive/$folderName/
cd /media/backupdrive/$folderName/
tar -C ${i:8} -czvf "${i:8}.tar.gz"
cd /root/multicraft/
done
Sorry for the image, it was on a virtual machine and I had to re-type it, because I couldn't copy and paste.
It looks to me like your tar command is missing its input (e.g., a final "."), and therefore says, "tar: Cowardly refusing to create an empty archive".
Your script appears to work for me with this tar command:
tar -C ${i#servers/} -czvf "${i#servers/}.tar.gz" .
I'd try a slightly different approach. tar by itself doesn't use temporary files, so you could tar the sources directly to the destination and compress them wizh gzip in a second step.
#!bin/bash
dst="/media/backupdrive/$(date +"%m-%d-%y")"
for d in servers/*; do
tarfile="$dst/${d#servers/}.tar"
tar -C "$d" -cvf "$tarfile" .
gzip -9 "$tarfile"
done

Resources