Unix - batch file to unzip folder with specific name - bash

I need a batch script for unix but I don't know it very well.
I have folder A and his subfolder
A\a1\b\c\file.zip
A\a2\b\c\otherFile.zip
A\a3\b\c\thirdFile.zip
Each zip file contains a xml file and a text file
The script have to do 2 things:
unzip all the zip files that are in all folder named 'c' of all sub
folder of 'A' ; the unzipped files should stay in the same folder in
which was the zip
all the unzipped files that have xml extension have to been renamed
someone can help me?
Thank you very much

You can do like this.
#find the folder 'c' and unzip all zip files
for folder in `find ./A -name c -type d`; do unzip $folder/data.zip -d $foler; done
#find all .xml files and change the extension to .edefg
for file in `find ./A -name *.xml -type f`; do mv "$file" "${file%.xml}.edefg"; done

You must go to all dir's.
Would be something like
find A -type d -name c | while read dir; do
cd ${dir} || continue
unzip -u *.zip
call_rename_xml_function
cd - # not needed in bash where this code is performed in a subshell
done
EDIT: Added -u flag for when the script is called twice.

Related

Loop through and unzip directories and then unzip items in subdirectories

I have a folder designed in the following way:
-parentDirectory
---folder1.zip
----item1
-----item1.zip
-----item2.zip
-----item3.zip
---folder2.zip
----item1
-----item1.zip
-----item2.zip
-----item3.zip
---folder3.zip
----item1
-----item1.zip
-----item2.zip
-----item3.zip
I would like to write a bash script that will loop through and unzip the folders and then go into each subdirectory of those folders and unzip the files and name those files a certain way.
I have tried the following
cd parentDirectory
find ./ -name \*.zip -exec unzip {} \;
count=1
for fname in *
do
unzip
mv $fname $attempt{count}.cpp
count=$(($count + 1))
done
I thought the first two lines would go into the parentDirectory folder and unzip all zips in that folder and then the for loop would handle the unzipping and renaming. But instead, it unzipped everything it could and placed it in the parentDirectory. I would like to maintain the same directory structure I have.
Any help would be appreciated
excerpt from man unzip
[-d exdir]
An optional directory to which to extract files. By default, all files and subdirectories are recreated in the current directory; the -d option allows extraction in an arbitrary directory (always assuming one has permission to write to the directory).
It's doing exactly what you told it, and what would happen if you had done the same on the command line. Just tell it where to extract, since you want it to extract there.
see Ubuntu bash script: how to split path by last slash? for an example of splitting the path out of fname.
putting it all together, your command executed in the parentDirectory is
find ./ -name \*.zip -exec unzip {} \;
But you want unzip to extract to the directory where it found the file. I was going to just use backticks on dirname {} but I can't get it to work right, as it either executes on the "{}" literal before find, or never executes.
The easiest workaround was to write my own script for unzip which does it in place.
> cat unzip_in_place
unzip $1 -d `dirname $1`
> find . -name "*.zip" -exec ./unzip_in_place {} \;
You could probably alias unzip to do that automatically, but that is unwise in case you ever use other tools that expect unzip to work as documented.

Shell script to extract all zip files in a directory and its sub directory, and copy the extracted files into another folder with same hierarchy

I have some zip files like below.
./etk/test/etf_time_series_am_update.zip
./etk/test/etf_time_series_am_delete.zip
./etk/dir1/etf_time_series_am_update.zip
./etk/dir1/etf_time_series_am_delete.zip
./etk/dir1/dir2/etf_time_series_am_update.zip
./etk/dir1/dir2/etf_time_series_am_delete.zip
./etk/dir1/dir2/dir3/etf_time_series_am_update.zip
./etk/dir1/dir2/dir3/etf_time_series_am_delete.zip
I want these files to unzip and store into the another folder. like
./newf/test/etf_time_series_am_update.txt
./newf/test/etf_time_series_am_delete.txt
./newf/dir1/etf_time_series_am_update.txt
./newf/dir1/etf_time_series_am_delete.txt
./newf/dir1/dir2/etf_time_series_am_update.txt
./newf/dir1/dir2/etf_time_series_am_delete.txt
./newf/dir1/dir2/dir3/etf_time_series_am_update.txt
./newf/dir1/dir2/dir3/etf_time_series_am_delete.txt
I tried with the find command and able to unzip, but couldn't copy in the destination folder.
I tried to unzip by following command. but have no idea about copy into the destination folder.
find -name '*.zip' -exec sh -c 'unzip -d "${1%.*}" "$1"' _ {} \;
This might be works for you.
find . -name "*.zip" | while read filename; do unzip -o -d "`dirname "$filename" | sed -r 's/etk/newf/g'`" "$filename"; done;
You may also get better solution by referring following links.
Finding-multiple-files-recursively-renaming
Recursively unzip

Unzip Folders to Parent Directory Keeping Zipped Folder Name

I have a file structure as follows:
archives/
zips/
zipfolder1.zip
zipfolder2.zip
zipfolder3.zip
...
zipfolderN.zip
I have a script that unzips the folders to the parent directory "archives", but it is unzipping the contents of the folders to the "archives" directory. I need the zipped folders to remain as folders under the "archives" directory. The resultant file structure should look like this:
archives/
zips/
zipfolder1.zip
zipfolder2.zip
...
zipfolder1/
contents...
zipfolder2/
contents...
...
I am currently using the following:
find /home/username/archives/zips/*.zip -type f | xargs -i unzip -d ../ -q '{}'
How can I modify this line to keep the original folder names? Is it as simple as using ../*?
You could use basename to extract the zip into the desired directory:
find /home/username/archives/zips/*.zip -type f -exec sh -c 'unzip -q -d ../"$(basename "{}" .zip)" "{}"' \;

unix command to copy all .h file with modified directory-structure

Suppose I have a folder structure like:
Libraries\
UIToolkit\
files\
toolkit.h
toolkit.c
toolkit.resource
NetworkLayer\
files\
network.h
network-info.txt
...
I need a command so that I can input the Libraries folder and specify a Output folder then in the Output folder I have:
Output\
UIToolkit\
toolkit.h
NetworkLayer\
network.h
Basically it:
copies all .h file and preserves the folder structure
also move all the headers to its sub-libraries' root folders no matter how deep they are in the sub-libraries sub-folders.
I was using rsync but it does not do 2nd step, so I guess I need some quick and dirty modification?
Thanks a lot!
A bit modified answer based on devnull's:
idir=$1
odir=$2
while read -r f; do
subdir=${f#$idir}
subdir=${subdir%%/*}
mkdir -p $odir/$subdir
cp -a $f $odir/$subdir
done < <(find $idir -type f -name "*.h")
call something like
./thisscript.sh Libraries Output
shall be able to work with absolute or relative directories, IMHO; but won't handle if .h file is right under Libraries (must be at least one subdir level down..).
You can say:
cd /path/to/Libraries
while read -r file; do
odir=$(cut -d'/' -f2 <<< ${file});
fname=$(basename ${file});
cp "$file" "/path/to/Output/${odir}/${fname}";
done < <(find . -type f -name "*.h")
This would copy all the *.h files to the Output folder as per the desired directory structure.

Bash script of unzipping unknown name files

I have a folder that after an rsync will have a zip in it. I want to unzip it to its own folder(if the zip is L155.zip, to unzip its content to L155 folder). The problem is that I dont know it's name beforehand(although i know it will be "letter-number-number-number"), so I have to unzip an uknown file to its unknown folder and this to be done automatically.
The command “unzip *”(or unzip *.zip) works in terminal, but not in a script.
These are the commands that have worked through terminal one by one, but dont work in a script.
#!/bin/bash
unzip * #also tried .zip and /path/to/file/* when script is on different folder
i=$(ls | head -1)
y=${i:0:4}
mkdir $y
unzip * -d $y
First I unzip the file, then I read the name of the first extracted file through ls and save it in a variable.I take the first 4 chars and make a directory with it and then again unzip the files to that specific folder.
The whole procedure after first unzip is done, is because the files inside .zip, all start with a name that the zip already has, so if L155.ZIP is the zip, the files inside with be L155***.txt.
The zip file is at /path/to/file/NAME.zip.
When I run the script I get errors like the following:
unzip: cannot find or open /path/to/file/*.ZIP
unzip: cannot find or open /path/to/file//*.ZIP.zip
unzip: cannot find or open /path/to/file//*.ZIP.ZIP. No zipfiles found.
mkdir: cannot create directory 'data': File exists data
unzip: cannot find or open data, data.zip or data.ZIP.
Original answer
Supposing that foo.zip contains a folder foo, you could simply run
#!/bin/bash
unzip \*.zip \*
And then run it as bash auto-unzip.sh.
If you want to have these files extracted into a different folder, then I would modify the above as
#!/bin/bash
cp *.zip /home/user
cd /home/user
unzip \*.zip \*
rm *.zip
This, of course, you would run from the folder where all the zip files are stored.
Another answer
Another "simple" fix is to get dtrx (also available in the Ubuntu repos, possibly for other distros). This will extract each of your *.zip files into its own folder. So if you want the data in a different folder, I'd follow the second example and change it thusly:
#!/bin/bash
cp *.zip /home/user
cd /home/user
dtrx *.zip
rm *.zip
I would try the following.
for i in *.[Zz][Ii][Pp]; do
DIRECTORY=$(basename "$i" .zip)
DIRECTORY=$(basename "$DIRECTORY" .ZIP)
unzip "$i" -d "$DIRECTORY"
done
As noted, the basename program removes the indicated suffix .zip from the filename provided.
I have edited it to be case-insensitive. Both .zip and .ZIP will be recognized.
for zfile in $(find . -maxdepth 1 -type f -name "*.zip")
do
fn=$(echo ${zfile:2:4}) # this will give you the filename without .zip extension
mkdir -p "$fn"
unzip "$zfile" -d "$fn"
done
If the folder has only file file with the extension .zip, you can extract the name without an extension with the basename tool:
BASE=$(basename *.zip .zip)
This will produce an error message if there is more than one file matching *.zip.
Just to be clear about the issue here, the assumption is that the zip file does not contain a folder structure. If it did, there would be no problem; you could simply extract it into the subfolders with unzip. The following is only needed if your zipfile contains loose files, and you want to extract them into a subfolder.
With that caveat, the following should work:
#!/bin/bash
DIR=${1:-.}
BASE=$(basename "$DIR/"*.zip .zip 2>/dev/null) ||
{ echo More than one zipfile >> /dev/stderr; exit 1; }
if [[ $BASE = "*" ]]; then
echo No zipfile found >> /dev/stderr
exit 1
fi
mkdir -p "$DIR/$BASE" ||
{ echo Could not create $DIR/$BASE >> /dev/stderr; exit 1; }
unzip "$DIR/$BASE.zip" -d "$DIR/$BASE"
Put it in a file (anywhere), call it something like unzipper.sh, and chmod a+x it. Then you can call it like this:
/path/to/unzipper.sh /path/to/data_directory
simple one liner I use all the time
$ for file in `ls *.zip`; do unzip $file -d `echo $file | cut -d . -f 1`; done

Resources