For starters I have checked most of the solutions available no
How to untar all .tar.gz with shell-script?
Unzipping multiple zip files in a directory?
I have a directory that has subdirectories with .gz files in them, and would like to extract all into either one folder or just keep them in their folders.
Thank you in advance
Problem
You want to decompress all compressed files inside a directory and all its subdirectories.
Solution
Use bash and the utility find to output to the console a list of all contents from the present directory. Use a looping construct to decompress each file.
Decompress all files in the current directory:
$ for file in `ls -1`; do
sudo tar -xvf "${file}" ; done
Decompress all archives in the current directory and any subdirectories (my personal favorite):
$ for file in `find *`; do
sudo tar -xvf "${file}" ; done
Decompress all archives recursively and do the same again for any remaining:
# Make the above loop a function to be called more than once
# In case of compressed files inside compressed files this will
# run twice the previous snippet.
$ function decompress_all_complete () {
function decompress_all () {
for file in `find *`; do
sudo tar -xvf "${file}" ; done
} ;
for i in `echo {1..2}`; do
decompress_all_complete; done
}
You could use variants of this for loop, if you like adventure :-)
$ for program in tar unzip untar ; do # You could simply add to this list...
for file in `find *`; do
sudo `which "${program}"` -xvf "${file}" ;
done ;
done
Discussion
The utility find lists everything from your present directory, and is fast. The snippet below will decompress the files one directory at a time each time but illustrates the simple logic of all the following code. Above are options and variations that do solve this problem; I was assuming at first that your present working directory contains all the files that you want to decompress to use the simplest version of the snippet.
This pseudo code tries to communicate the logic behind my solution briefly:
#Use all decompressing programs locally installed :: apropos compress
for --temp_container_1-- in --list_of_programs_to_decompress_files-- ; do
# run each program through every file in the current directory
for --temp_container_2-- in --list_of_files-- ; do
# use program with x options on y file
sudo "${temp_container_1}" [TYPE COMMON OPTIONS] "${temp_container_2} ;
# Successfully decompressed some files. Try another program.
done ;
# There is nothing else to do.
done
Context
I tested these snippets using or in:
* Linux debian 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt9-3 (2015-04-23) x86_64 GNU/Linux
* find (GNU findutils) 4.4.2
* GNU bash, version 4.3.33(1)-release (x86_64-pc-linux-gnu)
* tar (GNU tar) 1.27.1
If I understand your question, you could use something like
DEST=<Destination Folder>
SRC=<Src Folder>
find $SRC -name "*.tar.gz" -or -name "*.tgz" -exec tar xzvvf -C $DEST {} \;
In case you want to recursively untar into the same folder the archive was in, you can do the following:
for file in `find . -name '*.tar.gz'`; do \
DRN_NAME=$(dirname $file)
sudo tar -xzvf "${file}" -C $DRN_NAME ;
sudo rm $file
done
for file in `find . -name '*.tgz'`; do \
DRN_NAME=$(dirname $file)
sudo tar -xzvf "${file}" -C $DRN_NAME ;
sudo rm $file
done
Works on:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.1 LTS
Release: 20.04
Codename: focal
$ tar --version
tar (GNU tar) 1.30
$ find --version
find (GNU findutils) 4.7.0
$ bash --version
GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)
This should recursively extract all tar.gz files in the current directory and all sub-directories.
for subdir in `find . -type d`
do
for f in $subdir/*.tar.gz
do
tar -xzf $f -C <destination>
done
done
Related
I was searching for ways to create a bash file that would iterate all the folders in a directory, and create a tar.gz file for each of those directories.
(This is used specifically for ubuntu/drupal website - but could be useful in other scenarios.)
After lots of searching, combining scripts and testing, I found the following works very well when run from within the main directory.
This might be slightly different depending on version of bash, what version of ubuntu and from where you schedule or run the bash file. (Run by typing sh createDirectoryTarFiles.sh at command line from within the parent folder.)
The echo line is not necessary - just for viewing purposes.
for D in *; do
if [ -d "${D}" ]; then
tx="${D%????}"
echo "Directory is ${D} - and name of file would be $tx"
tar -zcvf "$tx.tar.gz" "${D}"
fi
done
You can use find to search for directories between mindepth and maxdepth and then create the tars
find . -maxdepth 1 -mindepth 1 -type d -exec tar czf $(basename {}).tar.gz {} \;
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
I have the folder a with two files (1,2), and the subfolder b with another two files (3,4).
I ´d like to tar a with '1,2,3,4' files in the tar file, but not including b.
(By default (tar cvf), b is added, and '3,4' are inside b. How can I do it?)
Thanks
you can use a script like this:
# ! /bin/sh
files=`cat list.list`
tarname="test.tar"
tarpath=`pwd`
#create empty tar
tar -cvf $tarpath/$tarname --files-from /dev/null
for curr_file in $files
do
#add each file separatly
cd `dirname $curr_file`
tar -uvf $tarpath/$tarname `basename $curr_file`
cd -
done
and create the filelist with a command like this:
find -type f > list.list
I have the following problem:
I have directorties a/b/c and inside c many text files.
I want to make a .tar.gz file in drectory a/mydir with the c directory inside and then unzip it to that same directory to create a/mydir/c (with all the files inside)
I am at directory a and run: (shell)
~:$ tar -czf mydir/output.tar.gz b/c
~:$ tar -zxf mydir/output.tar.gz -c mydir
but the result is directories a/mydir/b/c (with the files inside)
The problem is I don't want directory b in the middle, just c with all its contents
This works for me. Create data
mkdir -p a/b/c
echo 42 > a/b/c/file.dat
Archive
tar zc -f c.tar.gz -C a/b c
created a/b/c directories, from directory a kindly try this command.
so the file under b/c/files were done out.tar.gz
new directory "mydir" create under "b" and files extracted too.
out.tar.gz removed from "a".
# tar -cvzf out.tar.gz b/c/* ; mkdir -p b/mydir ; tar -xvzf out.tar.gz -C b/mydir/ ; rm -rf out.tar.gz
Thanks!
I tried this:
DIR=/path/tar/*.gz
if [ "$(ls -A $DIR 2> /dev/null)" == "" ]; then
echo "not gz"
else
tar -zxvf /path/tar/*.gz -C /path/tar
fi
If the folder has one tar, it works. If the folder has many tar, I get an error.
How can I do this?
I have an idea to run a loop to untar, but I don't know how to solve this problem
for f in *.tar.gz
do
tar zxvf "$f" -C /path/tar
done
I find the find exec syntax very useful:
find . -name '*.tar.gz' -exec tar -xzvf {} \;
{} gets replaced with each file found and the line is executed.
for a in /path/tar/*.gz
do
tar -xzvf "$a" -C /path/tar
done
Notes
This presumes that files ending in .gz are gzipped tar files. Usually .tgz or .tar.gz is used to signify this, however tar will fail if something is not right.
You may find it easier to cd /path/tar first, then you can drop the -C /path/tar from the untar command, and the /path/tar/ in the loop.
The accepted answer worked for me with a slight modification
for f in *.tar.gz
do
tar zxvf "$f" -C \name_of_destination_folder_inside_current_path
done
I had to change the forward slash to a backslash and then it worked for me.