Unzip files in subdirectories bash - bash

I have a directory called test1 which contains multiple directories. In each directory test1/*/, there is a *.gz file that I want to unzip. I tried writing this code but it doesn't work, any help would be appreciated.
for folder in test1/*/; do find . -name "*.gz" | while read filename; do gunzip -d $filename;done ;done

gunzip test1/*/*.gz
gunzip will extract the file in the directory it is in.

You can just do that using find:
cd test1
find . -name "*.gz" -execdir tar xzf '{}' \;
Remember that unzip command only works with .zip files.
PS: If .gz files have not been created using tar czf then use gunzip instead:
find . -name "*.gz" -execdir gunzip '{}' \;

I edited my command and it works now:
find ${path} -name "*.gz" | while read filename; do gunzip -d $filename; done

Related

extract text informations from many subfolders

I'm looking to extract informations from subfolders.
I have a folder containing several folders containing several folders with text file information.
I've done something like this, but it works only when text files have different names (otherwise files with same names are erased by the most recent ones):
mkdir target_directory
pwd=`pwd`
find $pwd . -name \*.txt -exec cp {} target_directory \;
cd target_directory
cat *.txt > all-info
rm *.txt
I was thinking to had directory to the name of extracted files. How can I do that?
Maybe there is a smarter way?
Thank you!
If your goal is to concatenate all *.txt files in target_directory/all-info then just use cat {} in the exec action of your find command and redirect the output:
$ mkdir -p target_directory
$ find . -type f -name '*.txt' -exec cat {} \; > target_directory/all-info
This should do the trick:
mkdir -p target_directory
find . -name "*.txt" -exec cat {} >> target_directory/all-info \;
Man-pages of cp mention:
-n, --no-clobber
do not overwrite an existing file (overrides a previous -i option)
So I think your solution (only the find part) should be:
find $pwd . -name \*.txt -exec cp -n {} target_directory \;

Error message when using find -exec to copy files

I use the find command to copy some files from one destination to another. If I do
$ mkdir dir1 temp
$ touch dir1/dir1-file1
$ find . -iname "*file*" -exec cp {} temp/ \;
everything works fine as expected, but if I do
$ mkdir SR0a temp
$ touch SR0a/SR0a-file1
$ find . -iname "*file*" -exec cp {} temp/ \;
> cp: `./temp/SR0a-file1' and `temp/SR0a-file1' are the same file
I get an error message. I do not understand this behavior. Why do I get an error by simply changing names?
That is because find searchs in SR0a/ folder at first, and then in temp/, and since you have copied into it the file, find founds it again in temp/ folder. It seems that find uses crafty sorting so it just should be take into account on use of find:
$ mkdir temp dir1 SR0a DIR TEMP
$ find .
.
./TEMP
./SR0a
./temp
./dir1
./DIR
So in case the dir1/ find founds the it at first, and this don't make such problems, let see the search sequence:
temp/
dir1/
When you search with SR0a the sequence is:
SR0a/
temp/
so found file is being copied into temp before searching it.
To fix it, either move temp/ folder outside the current one:
$ mkdir SR0a ../temp
$ touch SR0a/SR0a-file1
$ find . -iname "*file*" -exec cp {} ../temp/ \;
or use pipe to separate find and copy procedures:
$ find . -iname "*file*" | while read -r i; do cp "$i" temp/; done
This find should work:
find . -path ./temp -prune -o -iname "*file*" -type f -exec cp '{}' temp/ \;
-path ./misc -prune -o is used to skip ./temp directory while copying files to temp folder.
Your find command is also finding ./temp/*file* files and trying to copy them also into ./temp folder.
It is caused by the find that is trying to copied to it self.
Pipe output using while to separate with find command
Use cp with the option: -frpvT for match with file/dir target path
Print the realpath of the ouput file, see if the file path are the same.
find . -iname "*file*" | while read -r f; do echo cp -frpvT "$(realpath $f)" "/temp/$f"; done
If so, then correct the file path, when it is done then you can remove the echo from the command.

Extract tarball into the same directory

I have a hierarchy of folders, which contain a lot of tarballs. I need to write a script which recursively goes to each directory, extract the tarball in the corresponding directory.
I tried
find ./ -name "*.tar.gz" -exec /bin/tar -zxvf {} \;
The code executed with all the tarballs extracted to the pwd, not in the corresponding directory.
Please assist me on this if possible. Thanks :)
You can use find like this:
find . -name "*.tar.gz" -exec bash -c 'd=$(dirname "{}") && b=$(basename "{}") && cd "$d" && tar zxvf "$b"' \;
EDIT A shorter version of above find command will be:
find . -name "*.tar.gz" -execdir tar zxvf "{}" \;

Recursively unzip files and then delete original file, leaving unzipped files in place from shell

I've so far figured out how to use find to recursively unzip all the files:
find . -depth -name `*.zip` -exec /usr/bin/unzip -n {} \;
But, I can't figure out how to remove the zip files one at a time after the extraction. Adding rm *.zip in an -a -exec ends up deleting most of the zip files in each directory before they are extracted. Piping through a script containing the rm command (with -i enabled for testing) causes find to not find any *.zips (or at least that's what it complains). There is, of course, whitespace in many of the filenames but at this point syntaxing in a sed command to add _'s is a bit beyond me. Thank for your help!
have you tried:
find . -depth -name '*.zip' -exec /usr/bin/unzip -n {} \; -exec rm {} \;
or
find . -depth -name '*.zip' -exec /usr/bin/unzip -n {} \; -delete
or running a second find after the unzip one
find . -depth -name '*.zip' -exec rm {} \;
thx for the 2nd command with -delete! helped me a lot..
just 2 (maybe helpful) remarks from my side:
-had to use '.zip' instead of `.zip` on my debian system
-use -execdir instead of -exec > this will extract each zip file within its current folder, otherwise you end up with all extracted content in the dir you invoked the find cmd.
find . -depth -name '*.zip' -execdir /usr/bin/unzip -n {} \; -delete
THX & Regards,
Nord
As mentioned above, this should work.
find . -depth -name '*.zip' -execdir unzip -n {} \; -delete
However, note two things:
The -n option instructs unzip to not overwrite existing files. You may not know if the zip files differ from the similarly named target files. Even so, the -delete will remove the zip file.
If unzip can't unzip the file--say because of an error--it might still delete it. The command will certainly remove it if -exec rm {} \; is used in place of -delete.
A safer solution might be to move the files following the unzip to a separate directory that you can trash when you're sure you have extracted all the files successfully.
Unzip archives in subdir based on the file name (../file.zip -> ../file/..):
for F in $(find . -depth -name *.zip); do unzip "$F" -d "${F%.*}/" && rm "$F"; done
I have a directory filling up with zipped csv files. External processes are writing new zipped files to it often. I wish to bulk unzip and remove the originals as you do.
To do that I use:
unzip '*.zip'
find . | sed 's/$/\.zip/g' | xargs -n 1 rm
It works by searching and expanding all zip files presently in the directory. Later, after it finishes there are potentially new unzipped new files mixed in there too that are not to be deleted yet.
So I delete by finding successfully unzipped *.csv files, and using sed to regenerate the original filenames for deletion which is then fed to rm via the xargs command.

using find with exec

I want to copy files found by find (with exec cp option) but, i'd like to change name of those files - e.g find ... -exec cp '{}' test_path/"test_"'{}' , which to my test_path should copy all files found by find but with prefix 'test'. but it ain't work.
I'd be glad if anyone could give me some ideas how to do it.
best regards
for i in `find . -name "FILES.EXT"`; do cp $i test_path/test_`basename $i`; done
It is assumed that you are in the directory that has the files to be copied and test_path is a subdir of it.
if you have Bash 4.0 and assuming you are find txt files
cd /path
for file in ./**/*.txt
do
echo cp "$file" "/test_path/test${file}"
done
of with GNU find
find /path -type f -iname "*.txt" | while read -r -d"" FILE
do
cp "$FILE" "test_${FILE}"
done
OR another version of GNU find+bash
find /path -type f -name "*txt" -printf "cp '%p' '/tmp/test_%f'\n" | bash
OR this ugly one if you don't have GNU find
$ find /path -name '*.txt' -type f -exec basename {} \; | xargs -I file echo cp /path/file /destination/test_file
You should put the entire test_path/"test_"'{}' in ""
Like:
find ... -exec cp "{}" "test_path/test_{}" \;
I would break it up a bit, like this;
for line in `find /tmp -type f`; do FULL=$line; name=`echo $line|rev|cut -d / -f -1|rev` ; echo cp $FULL "new/location/test_$name" ;done
Here's the output;
cp /tmp/gcc.version new/location/test_gcc.version
cp /tmp/gcc.version2 new/location/test_gcc.version2
Naturally remove the echo from the last part, so it's not just echo'ng what it woudl of done and running cp

Resources