views:

431

answers:

1

Here's my situation. A project has as objective to migrate some attachments to another system.

These attachments will be located to a parent folder, let's say "Folder 0" (see this question's diagram for better understanding), and they will be zipped/compressed.

I want my batch script to be called like so:

BatchScript.bat "c:\temp\usd\Folder 0"

I'm using 7za.exe as the command line extraction tool.

What I want my batch script to do is to iterate through the "Folder 0"'s subfolders, and extract all of the containing ZIP files into their respective folder.

It is obligatory that the files extracted are in the same folder as their respective ZIP files. So, files contained in "File 1.zip" are needed in "Folder 1" and so forth.

I have read about the FOR...DO command on Windows XP Professional Product Documentation - Using Batch Files.

Here's my script:

@ECHO OFF

FOR /D %folder IN (%%rootFolderCmdLnParam) DO 
    FOR %zippedFile IN (*.zip) DO 7za.exe e %zippedFile

I guess that I would also need to change the actual directory before calling 7za.exe e %zippedFile for file extraction, but I can't figure out how in this batch file (through I know how in command line, and even if I know it is the same instruction "cd").

EDIT #1

I have already received some tips on ServerFault to the same question. Please see the answers at this link.

However, it extracted from the root (C:), and not from the given in parameter folder.

Anyone has an idea?

EDIT #2

It seems that batch script doesn't handle folder and file names containing a space character adequately. Can anyone confirm what I think?

EDIT #3

I need it to be fully recursive, since I don't know the directory structure against which this will be used.

EDIT #4.a

With @aphoria's solution, I'm almost there! The only problem is that it takes let's say File5.zip, retrieve the filename only to get File5, creates a subfolder File5 and extract the File5.zip to File5 subfolder, then, it wants to create a File5 subfolder in Folder 1, where it should instead want to create File1 subfolder, to stick with my example.

EDIT #4.b

As required, here's the code as it currently look:

@echo off

setlocal enableextensions enabledelayedexpansion

rem
rem Display instructions when no parameter is given.
rem
if "%1" equ "" (
    echo Syntaxe : od.bat ^<directory mask>^
    echo Exemple : od.bat *
    goto :Eof
)

rem
rem Setting the PATH environment variable for this batch file for accessing 7za.exe.
rem
path=c:\temp;%PATH%

rem
rem Removing quotes from the given command line parameter path.
rem
set root=%1
set root=%root:~%1
set root=%root:~0,-1%

rem Searching directory structure from root for subfolders and zipfiles, then extracting the zipfiles into a subfolder of the same name as the zipfile.
for /F "delims==" %%d in ('dir /ogne /ad /b /s %root%') do (
    echo Traitement du dossier : "%%d"

    for /F "delims==" %%f in ('dir /b "%%d\*.zip"') do (
        rem Getting filename without extension.
        set subfolder=~n%f
        mkdir "%%d\%subfolder%"
        rem Extracting zipfile content to the newly created folder.
        7za.exe e "%%d\%%f" -o"%%d\%subfolder%"
    )
)

:Eof

endlocal

Ideas anyone?

My guess is that it digs one directory hierarchy at a time. Here's the deal. Consider we have a Folder A in Folder 1 (Folder 1\Folder A), then, it searches from Folder 1 through Folder 5, and comes back to Folder 1\Folder A, where the %subfolder% variable sticks with its last value.

Anyone's help is gratefully appreciated.

+1  A: 

I'm not very familiar with the 7zip command-line options, so you will need to figure out the exact command for that, but the script below will take a fully specified path (spaces allowed) and print out the the folder name and .zip files contained within it.

@ECHO OFF

REM
REM Remove the double quotes from the front and end of the root path
REM
SET ROOT=%1
SET ROOT=%ROOT:~1%
SET ROOT=%ROOT:~0,-1%
ECHO %ROOT%

FOR /F "DELIMS==" %%d in ('DIR "%ROOT%" /AD /B') DO ( 
  ECHO %%d
  FOR /F "DELIMS==" %%f in ('DIR "%ROOT%\%%d\*.zip" /B') DO (
    ECHO   %%f
  )
)  


Run it like this:

MyScript.CMD "c:\temp\usd\Folder 0"

You should get output similar to this:

Folder A
  File 1.zip
  File 2.zip
Folder B
  File 1.zip
  File 2.zip  


UPDATE

The code below will extract Folder A\File 1.zip to a new folder Folder A\File 1.

A few things to keep in mind:

  1. In the first FOR loop, you need to have %ROOT% enclosed in double quotes to handle folders with spaces in the name.
  2. Since you're SETting a variable inside the second FOR, you need to put SETLOCAL ENABLEDELAYEDEXPANSION at the beginning. Then, reference the variable using ! (for example, !subfolder!) to force expansion at runtime.
  3. This line of your code set subfolder=~n%f should be this set subfolder=%%~nf
  4. I put ECHO in front of the MKDIR and 7za.exe commands to test. Once you are sure it is doing what you want, remove the ECHO statement.

Here is the code:

@ECHO OFF

SETLOCAL ENABLEDELAYEDEXPANSION

REM
REM Remove the double quotes from the front and end of the root path
REM
SET ROOT=%1
SET ROOT=%ROOT:~1%
SET ROOT=%ROOT:~0,-1%
ECHO %ROOT%

REM Searching directory structure from root for subfolders and zipfiles,
REM then extracting the zipfiles into a subfolder of the same name as the zipfile.

FOR /F "delims==" %%d IN ('dir /ogne /ad /b /s "%ROOT%"') DO (
    ECHO Traitement du dossier : "%%d"

    FOR /F "delims==" %%f IN ('dir /b "%%d\*.zip"') DO (
        REM Getting filename without extension.
        SET subfolder=%%~nf
        ECHO mkdir "%%d\!subfolder!"
        REM Extracting zipfile content to the newly created folder.
        ECHO 7za.exe e "%%d\%%f" -o"%%d\!subfolder!"
    )
)

ENDLOCAL
aphoria
Thanks for you answer! =) Now, to make your solution fully recursive, how should I go?
Will Marcouiller
Add a `/S` to the `DIR "%ROOT%" /AD /B` command.
aphoria
We're almost there! Thanks to you and the solution provided! =) The only thing I now have to deal with is this: > It always want to create the same subfolder everywhere it has to extract a zipfile. See my edit. =)
Will Marcouiller
I'm not sure I'm fully understand. Can you update the question with your code as it currently looks?
aphoria
@aphoria: Please see my code in **EDIT #4.b**. Thanks for your help! =)
Will Marcouiller
@Will I updated my answer checkout the UPDATE section.
aphoria
@aphoria: I just edited your answer to illustrate the tiny change I have made: `-o"%%d\!subfolder!"`, instead of `-o"%%d\%subfolder%"`.
Will Marcouiller
@aphoria: Thanks very much for your great help! There is one thing I'd like to know though, how does "!" work in batch file? (By the way, I added a link to your answer on ServerFault where I was aksing the same question. Thanks for your kind help!) Here's the link to show you my gratitude: http://serverfault.com/questions/149317/iterating-through-folders-and-files-in-batch-file
Will Marcouiller
@Will Cool, I'm glad I could help. When `ENABLEDELAYEDEXPANSION` is on, the `!` is used to force variable expansion at runtime. If you use `%`, the variable is expanded at the beginning of the script and that is it. Are you more confused? :) Look at `SET /?` in a command window, towards the bottom there is an explanation of delayed expansion. Thanks for the link from SF. :)
aphoria
@aphoria: Thanks for the hint about `!`. I just read `SET /?` as suggested. I can now understand that its value will be evaluated at runtime, if I may resume like so. That is why it allows for value changes. This works indeed if `ENABLEDELAYEDEXPANSION` is enabled. So new features for me! I have written some batch file many many years ago, like almost 20 years back in `DOS 5.0`. Hehehe... Thanks friend! =)
Will Marcouiller