0

I'm trying to create a batch file script that will compress all subfolders named folder1 within a directory, BUT it should only compress this folder if it does NOT contain another subfolder with the same name.

I am very new to cmd and batch files, and this is also my first post of stack overflow, please let me know if I've failed to give some information that I should!

The bit of pseudo-ish code below hopefully illustrates what I'm trying to accomplish:

@echo off
SETLOCAL EnableDelayedExpansion

FOR /D /R %%G IN (*folder1*) DO (
   CD %%G
   SET /A compress=true
   FOR /D /R %%H IN (*folder1*) DO (
      ECHO folder contains another folder of same name, should not be compressed
      SET /A compress=false
   )
   IF !compress!==true (
      ECHO Run compression operation on folder
      "C:\Program Files (x86)\7-zip\7z.exe" a -tzip "%%G.zip" "%%G\"
   )
)

Please ask away if anything seems unclear! I'm really hoping to turn the above into functional code, thank you in advance for any input or thoughts.

  • 1
    Possible duplicate of [Variables are not behaving as expected](https://stackoverflow.com/questions/30282784/variables-are-not-behaving-as-expected). BTW, what do you think by the `%compress%=false` line? – JosefZ Mar 31 '19 at 18:19
  • Sorry I realized ```%compress%=false``` was the wrong way to assign a new value to the variable. I think the ```SET /A compress=false``` replacement is the correct use with ```SETLOCAL EnableDelayedExpansion```. Edited the code. – ShieldHeart Mar 31 '19 at 19:28
  • No need for `set /A`, a normal `set` suffices. Anyway, what about using `if exist`, which also accepts wild-cards? – aschipfl Apr 01 '19 at 06:15

1 Answers1

0
@ECHO OFF
SETLOCAL
:: Starting directory
SET "sourcedir=U:\sourcedir"
:: name of directory to compress
SET "targetname=targetdir"
FOR /d /r "%sourcedir%" %%a IN (*) DO (
  IF /i "%%~nxa" == "%targetname%" IF NOT EXIST "%%a\%targetname%\." (
   ECHO compress %%a
   rem temporarily switch to target directory
   PUSHD "%%a"
   ECHO 7z a -tzip "%%a.zip" 
   rem back to original directory
   POPD
  )
)

GOTO :EOF

This should do as you want - it will echo not execute the 7z command.

The if sees whether the "name and extension" portion of the directory-name in %%a matches the target (the /i makes the match case-insensitive). If it matches AND there is a subdirectory with the required name, then the compression portion is executed.

There are two points to consider.

First, the name of the destination ZIP file. As you have written it, the ZIP generated would be folder1.zip in the parent directory. IDK what you want here. This code would do the same, but %%a.zip could be replaced by ..\%targetname%.zip since the pushd/popd changes the current directory to the folder1 directory and .. means the parent directory.

The second matter is whether or not you want to compress ...\folder1\folder1 (which would have a destination ZIP file of ...\folder1\folder1.zip)


Revision given comment:

@ECHO OFF
SETLOCAL
:: Starting directory
SET "sourcedir=U:\sourcedir"
:: name of directory to compress
SET "targetname=targetdir"
REM (
FOR /d /r "%sourcedir%" %%a IN (*) DO IF /i "%%~nxa" NEQ "%targetname%" (
 rem calculate parent name in %%~nxp and grandparent in %%~nxg
 FOR %%p IN ("%%~dpa.") DO FOR %%g IN ("%%~dpp.") DO (
  IF /i "%%~nxp" == "%targetname%" IF /i "%%~nxg" NEQ "%targetname%" (
   ECHO child   %%~nxa 
   ECHO parent  %%~nxp
   ECHO Gparent %%~nxg   Gppath=%%~dpg
   ECHO compress %%a
   rem temporarily switch to target directory
   PUSHD "%%a"
   ECHO 7z a -tzip "%%a.zip" 
   ECHO -------------------
   rem back to original directory
   POPD
  )
 )
)

GOTO :EOF

It's not that clear what you want to do with a directory named ...\folder1\folder1\something or what the target ZIP file-name should be.

The if in the for /d /r line will ensure that only leaf-names that do not match the target name are processed. The path-name in %%a is then processed into the parent and grandparent portions - note that %%~dp? is the drive+path portion of %%? which terminates \ so appending . to this resolves to effectively removing the terminal \ yielding a "filename".

You appear to want to compress directories that have a parent but not a grandparent named with the target string, hence the innermost if statement.

I've just echoed the various strings available at this point so they may be strung together as required to form your destination ZIP file-name. Note that the pushd/popd bracket ensures that the current directory at the time of the compress is the leaf to be compressed.

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • Thank you kindly this seems to be working like a charm! If I may ask a follow up as I failed to add this in the first time... When the conditions to compress the folder are met, I would actually like to compress the folder found within folder1 (with this subfolder's original name and hierarchy under ```folder1```), rather than compress folder1 itself. The folder within ```folder1``` can have any name, but there will always only be a single folder within it to compress. How would the code change to implement this? I suspect only the code within the IF statement should change correct? – ShieldHeart Mar 31 '19 at 21:42