user3882389
user3882389

Reputation: 56

How to pushd mutliple folders on Windows batch

How can I include multiple paths? Like for example:

pushd C:\Users\Downloads\back\dotNet 
      C:\Users\Downloads\back\MySQL

And exclude every file with extension .log

7za.exe a -tzip -mx5 -x!\*.log* "C:\Users\Desktop\Downloadbak-%TODAY%.zip"
popd


ECHO.

PAUSE

Upvotes: 1

Views: 3264

Answers (3)

CristiFati
CristiFati

Reputation: 41116

There are actually 2 questions here:

  • pushd

  • 7z(a).exe

Regarding pushd: a simple answer to your question is: It can't be done.
pushd (push directory) and popd (pop directory) operate on a stack like structure - operations on a stack are push and pop

  • push has an argument and inserts it over the current stack top (the last element inserted), if any, and thus that becomes the stack top
  • pop simply takes the top of the stack out and making the next element of the stack (if any) its top

So:

  • pushd inserts the current dir (%CD%) on the top of an internal stack and changes the current directory to the directory that it got as an argument
  • popd changes the current directory to the top of the (same) internal stack and also removes it from the stack

But your desired behavior can be achieved by a sequence of pushd / popd commands, and there is one aspect that needs to be clear: pushd and popd commands order is reversed - explanation below:

Let's assume that the internal stack is empty: you're located in ${DIR1} (this is a directory full path somewhere in your filesystem). As a note, Nix style variables (${...}) are just (directory) placeholders:

  • You execute:

    pushd ${DIR1}
    
  • This inserted ${DIR1} in the stack and changed your current dir to ${DIR2} (this is where you are located). Then you execute:

    pushd ${DIR3}
    
  • This inserted ${DIR2} on the stack (on top of ${DIR1}) and changed the current dir to ${DIR3} (this is where you are located). Now, you do your operations, and want to get back, so you execute:

    popd
    
  • This takes out ${DIR2} (the last one that was pushded) from the stack and changes the current directory to it (you will be located in ${DIR2}). And finally when executing again:

    popd
    
  • ${DIR1} is being removed from the stack (and thus the stack becomes empty - as it was at the beginning) and it changes the current directory to it, so you will be located in ${DIR1} just like before the 1st pushd command

Now, regarding the 7zip executable (I see that you typed 7z a.exe, while on my computer is 7z.exe (just installed it)):

It seems that your filter is perfectly fine, but it only strips the log files from he current directory, the sub directories seem to ignore the -x flag. So, I tested and it turns out that if I pass -r (recursive) it will also strip out all the .log files from sub-directories (although I can't explain why your pattern doesn't work with directories - maybe it only refers to base file names?).

Here's the command (notice that I removed the \ before the *):

7z.exe a -tzip -mx5 -r -x!*.log somefile.zip

Upvotes: 4

Safwan
Safwan

Reputation: 360

A bit late to the scene but here goes anyways. Below is an implementation of a stack data structure in Windows batch scripting.

Features:

  • You must call the :InitializeStack subroutine before using the stack.
  • Push items on the stack by calling the :Push subroutine.
  • Pop items off the stack by calling the :Pop subroutine.
  • The variable $Count will always contain the count of items in the stack.
  • The variable $Top will always contain the most recent item added to the stack.
  • The variable $Bottom will always contain the first item added to the stack.
  • You can dump the content of the stack by calling the :DumpStack subroutine.
  • The type of items that you can push on the stack is anything that can be stored in a variable. For example, Call :Push "String 1", Call :Push "%1", Call :Push "%MyVariable%", etc.

I use the stack in my batch files to keep track of subroutine calls. Every subroutine in my batch files starts with Call :Push %0, which pushes the current subroutine's name onto the stack and ends with Call :Pop.

Some may find it an over-kill for batch scripting but I enjoyed creating it and I hope someone will find this useful, enjoy.

@Echo Off
Cls
SetLocal
SetLocal EnableExtensions
SetLocal EnableDelayedExpansion

Call :InitializeStack

Call :Push "String 1"
Call :Push "String 2"
Call :Push "String 3"
Call :Pop

Echo Total items in stack = !$Count!
Echo Top of stack         = !$Top!
Echo Bottom of stack      = !$Bottom!
Call :DumpStack

Goto End

:InitializeStack
:------------------------------------------------------------
Set "$Stack[0]=0"
Set "$Count=!$Stack[0]!"
Set "$Top="
Set "$Bottom="
Exit /b

:DumpStack
:------------------------------------------------------------
If !$Stack[0]! EQU 0 (
  Echo Stack is empty.
) Else (
  Echo.
  Echo Stack Dump
  Echo ----------
  For /l %%a In (!$Stack[0]!,-1,1) Do (Echo !$Stack[%%a]!)
)
Exit /b

:Push <String>
:------------------------------------------------------------
Set /a "$Stack[0]+=1"
Set "$Count=!$Stack[0]!"
Set "$Top=%~1"
Set "$Bottom=!$Stack[1]!"
Set "$Stack[!$Stack[0]!]=!$Top!"
Exit /b

:Pop
:------------------------------------------------------------
If !$Stack[0]! EQU 0 (
  Echo "Stack is empty."
) Else (
  Set "$Stack[!$Stack[0]!]="
  Set /a "$Stack[0]-=1"
  Set "$Count=!$Stack[0]!"
  If !$Stack[0]! GTR 0 (
    For %%a In (!$Stack[0]!) Do Set "$Top=!$Stack[%%a]!"
    Set "$Bottom=!$Stack[1]!"
  ) Else (
    Set "$Top="
    Set "$Bottom="
  )
)Exit /b

:End

To place all your paths on the stack, use the following command:

For %%a In ("<path1>" "<path2>") Do Call :Push "%%~a"

To carry out an action on the items on the stack, you can use:

For /l %%a In (!$Stack[0]!,-1,1) Do (pushd !$Stack[%%a]!)

Upvotes: 0

user330315
user330315

Reputation:

Simple answer: you can't.

pushd changes the current directory to the directory you supply and before changing the directory it saves the current one on the stack.

But there can only be a single "current" directory thus it does not make sense (nor could it work) to supply more than one directory to the pushd command.

Upvotes: 1

Related Questions