Batch file to move between symmetric folder structures - windows

I work in a project with symmetric folder structure, i.e:
Master
Folder1
Folder_A1
Folder2
Folder3
Slave
Folder1
Folder_A1
Folder2
Folder3
While I'm working, I usually change between master and slave to the same directories. I want to create a batchfile that helps me to switch only the maste/slave directory with this, i want something like this:
C:\Project\Master\Folder1\FolderA1>BatchFile
C:\Project\Slave\Folder1\FolderA1>
I plan to create 2 batches, toMaster and toSlave, that takes the current directory and replaces the "Master" String with the "Slave" and then move to that directory. Heres what I have so far in the toSlave batch:
#echo OFF
setlocal ENABLEDELAYEDEXPANSION
set word=Slave
set "str=%cd%"
echo %str%
set str=%str:Master=!word!%
echo %str%
pushd %str%
This seems to replace the strings correctly but when I run it from a terminal, it doesn't change my current directory. Any idea ?
Thanks

Your approach doesn't work, because you did a setlocal. When the batch file ends, an implicite endlocal is executed, which undoes pushd. There is another reason you shouldn't use pushd: it saves the current location on a stack and doing it too often, may lead to a stack overflow. Better use cd instead.
Your batch file is very overloaded. Most of the lines are not needed and you can do the rest in just one command.
All you need for toSlave.bat is:
#cd /d "%__cd__:\Master\=\Slave\%"
(or you use #Compo's "Toggle" approach. It's quite elegant, but it's your job then to verify you are in the correct folder)

Related

Run program in subfolders

I'm trying to write a Windows batch script to run 2 programs through a bunch of folders. I'm not an expert at shell scripting but I try my best.
Here's what I'm trying to run through each folder...
The input for program1 is a .extension1 file which then produces a .extension2 file which then is run through program2 to generate what I need.
Before I run the script I cd into the folder. The programs are copied to the folder because they only work in the current working directory.
copy C:\program1 .
copy C:\program2 .
for %i in (*.extension1) do program1 "%i"
for %i in (*.extension2) do program2 "%i"
The data folder shown above contains hundreds of folders that I need to run the program in. I'd like to be able to do this in one big batch script.
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir\one"
PUSHD "%sourcedir%"
FOR /r %%a IN (*.ext1) DO (
PUSHD "%%~dpa"
ECHO(c:\program1 "%%~nxa"
popd
)
popd
GOTO :EOF
You would need to change the setting of sourcedir to suit your circumstances.
In all probability, this is all you would need - or at least, this is a framework.
Note that the routine will simply ECHO the required commands. This allows a harmless test (on a representative sub-tree) to ensure that the process should work on the entire tree.
Changing ECHO(c:\program1 to c:\program1 should execute the first program on each .ext1 file in the sub-tree. It would be unusual for a program to check that the file exists within the same directory as the executable - if it won't take a path, then "the current directory" would be assumed.
You don't say whether the program program1 produces a file called whatever.ext2 from whatever.ext1 or whether it produces somethingradicallydifferent.ext2. In all probability, the same name would be used.
If that is the case, then to run the second program, simply add after
ECHO(c:\program1 "%%~nxa"
ECHO(c:\program2 "%%~na.ext2"
Otherwise, simply repeat the entire block, changing ext1 to ext2
(I'll assume you can figure out that I've abbreviated the extensions)
If, on the off-chance the program(s) need to be in the same directory, then replace
ECHO(c:\program1 "%%~nxa"
with
echo n|C:\program1 . >nul 2>nul
ECHO(program1 "%%~nxa"
(and ditto for program 2, obviously). Here the n is echoed into the copy, so that the copy will only take place once. This could be improved but is probably only a theoretical requirement anyway since it's 99.9999% likely that executing c:\program? will work quite happily.

How to write a batch file to set svn:ignore for a particular directory in every branch of a directory tree?

To explain with an example, the structure of my project is RootDirectory, there are inside it 3 branch directories DirA, DirB and DirC.
Let's say the target folder is bin folder. bin is present directly in dirC, under 1 level in dirB( DirB->Dir BA-> bin) and under two levels in DirA (DirA->DirAA->DirAAA->bin).
Now I have to run a batch script in root directory that should transverse the entire tree, search for bin folders and put svn ignore only on bin folders.
With my current program, I can transverse, but the loop is running for the subfolders of bin also. Thus am unable to stop at bin, go into that and implement svn:ignore.
The requirement in gist:
Outer loop to transverse the entire tree
Inner loop to stop at bin, cd to bin, implement svn ignore, break.
Outer loop continues to next instance of bin.
You could recursively call a batch file to achieve this.
An example batch file called recursive.bat could look like this (note: this is just to get you started, you might have to do extra things to deal with file names and directories with spaces in them and possibly other anomalies...):
#ECHO OFF
SETLOCAL
IF "%1"=="" (
SET BATDIR=%~dp0
) ELSE (
SET BATDIR=%1
)
ECHO Currently in %CD%
REM Trick to get current directory name (not path)
FOR %%* IN (.) DO (
IF %%~n*==bin (
REM Currently inside a directory called bin
ECHO Setting SVN prop for %CD% and exiting recursion...
REM Insert your SVN ignore command here
GOTO :EOF
)
)
REM Loop over all subdirectories in this directory
FOR /D %%D IN ("*") DO (
ECHO Recursing into subdir "%%D"
PUSHD "%%D"
CALL "%BATDIR%\recursive.bat"
POPD
)
Invoke it as recursive.bat (no parameters). The current directory trick is copied from Get current folder name by a DOS command?
By the way, if you happen to use TortoiseSVN then you can instruct it via configuration settings to always ignore bin directories.

How would I run a batch program from another batch program within its own environment?

I need to run a batch file located in another folder that must be called from another batch file.
Whenever I do call this batch file from the first, let's call them Batch_A and Batch_B, respectively, the second tries to run from the directory of the first batch file.
Batch_A needs to call or start Batch_B, however Batch_B needs to run as if I were to manually double-click it myself.
This is what I currently have at the end of my first batch
start "A thing" "%output%\thing.bat" /b
Have you looked into push or pop.
Before calling the second batch file, enter the "push" command:
pushd %dynamicdirectory%
Call batchfileb.bat
popd
If Batch_B is designed/written to be always run from the direcory where it is located
you might also consider to modify Batch_B.bat
setlocal
cd /D %0\..
REM your original content
endlocal
In %0 the path to the batchfile is stored.
The trick is to assume %0 is a directory then to change one level lower
based on that diretory.
With /D also the drive letter is changed correctly.
The cd command doesn't care if %0 is really a directory.
In fact %d doesn't even have to exist (%0\dummy\..\.. would also work).
The setlocal command is to have the working directory beeing restored
when Batch_B.bat has finished.
I noticed that the endlocal command is not really necessary
in this context since it is applied imlicitely when Batch_B finishes.

Starting batch file command prompt from the directory location in which the batch file resides in

I am writing a batch file that uses some of the files within it's parent directory (lets say Folder1).
C:\User\Steve\Foder1\
Now I want to make the whole Folder_1 relocatable so that I can copy paste the folder anywhere on my/someone else's computer and run batch script.
D:\User\Random_guy\Folder1\
The question is how do I start batch file's command prompt to (D:\User\Random_guy\Folder1) it's parent directory without writing another batch script to do that.
Start your batch file with:
pushd %~dp0
That will set the current directory to be the folder containing the batch file. Then in the batch file, make sure all your paths are relative to the current directory.
However, if your batch file changes to other directories in the course of its execution and you would still like to be able to refer to the batch's home folder's contents without knowing the exact path, use the same %~dp0 as the path to the file(s) you want to use. For instance, a FileA from the same folder as the batch file would be addressed as
"%~dp0FileA"
Note the absence of a \ before the FileA. This is because the %~dp0 already includes a trailing \ and so the entire thing will evaluate to a correct path all right. (Although if you do put another backslash, like "%~dp0\FileA", it should work as well, because Windows usually disregards multiple consecutive backslashes when in the middle of a path.)
%CD% in a batch file gets the current directory/directory batch is being run in.
So - if I've got this right, you want to run
`C:\steve\folder1\yourbat.bat`
which should copy C:\steve\somefiles to D:\Random_guy and set the current directory to D:\Random_guy\folder1 ?
#ECHO OFF
SETLOCAL
SET subdir=folder1
SET destdir=%~1
IF NOT DEFINED destdir ECHO Require destination username&GOTO :EOF
SET destdir=%~1\%subdir%
:: Ensure destination exists
ECHO MD "%destdir%" 2>nul
SET "sourcefrom=%~dp0.."
ECHO COPY "%sourcefrom%\filestocopy" "%destdir%\..\"
ECHO CD /d "%destdir%"
Note that the MD, COPY and CD commands are merely ECHOed, you'd need to remove the ECHO keyword to execute them.
Run the batch with a parameter of D:\Random_guy

Windows Batch move to directory that may not exist

In a Windows batch file I am trying to move a file to a directory which may not currently exist. Because the directory is not there, when I do the move I see an error like:
The system cannot find the path specified
move c:\aaa\bbb\ccc\ddd\myfile.txt c:\aaa\111\222\333\444\mytext.txt
How can I easily create the path that I want to move to if it doesn't currently exist? For example here, directory 111 may not exist yet under aaa. I want the whole path structure to be created and then the file moved.
I had thought that it would just create the whole path for me as part of the move.
Try:
md c:\aaa\111\222\333\444 2> nul
before your Move command.
md makes directories recursive, so if there are no parent directories to 444, it will keep creating hierarchically. The "2> nul" ensures that if you have the directory already, your command wouldnt error out.
If ROBOCOPY is an option, it will create the folder structure if it doesn't exist.
Try this:
ROBOCOPY c:\aaa\bbb\ccc\ddd c:\aaa\111\222\333\444 mytext.txt /MOV
if not exist c:\aaa\111\222\333\444 md c:\aaa\111\222\333\444
Move c:\aaa\bbb\ccc\ddd\myfile.txt c:\aaa\111\222\333\444\mytext.txt
Continuing on Aruns answer:
md c:\aaa\111\222\333\444\mytext.txt
rd c:\aaa\111\222\333\444\mytext.txt
move c:\aaa\bbb\ccc\ddd\myfile.txt c:\aaa\111\222\333\444\mytext.txt
This creates a folder called mytext.txt and its parents, and then deletes it, but not the parents.
More fun:
call :move_md "c:\aaa\bbb\ccc\ddd\myfile.txt" "c:\aaa\111\222\333\444\mytext.txt"
call :move_md "c:\aaa\bbb\ccc\ddd\myfile1.txt" "c:\aaa\111\222\333\444\mytext4.txt"
call :move_md "c:\aaa\bbb\ccc\ddd\myfile2.txt" "c:\aaa\111\222\333\444\mytext5.txt"
call :move_md "c:\aaa\bbb\ccc\ddd\myfile3.txt" "c:\aaa\111\222\333\444\mytext6.txt"
goto :eof
:move_md
md %2
rd %2
move %1 %2
goto :eof
Lets say you have the following directory structure.
C:\aaa\bbb\ccc\ddd
you want to create a directory called 111 under aaa, then 222 under 111, then 333 under 444 and so on
Window's cmd allows you to create a directory structure by providing multi level path
thus
md c:\aaa\111\222\333\444 will create all the directory till 444.
You may want to create the directory first and then perform the move
Continuing on johvs answer: I really love the idea, but if you have a larger number of files this will not work due to performance limitations. It took ~8.5s per file, and I have about 3mio files to move, which makes a total computation time of roughly ten months. With this option out of the field I have found this 2-step-solution - first copy the folder structure, and only then copy the files:
xcopy C:\source C:\target /t /e
move C:\source\aaa\bbb\ccc\ddd\myfile.txt C:\target\111\222\333\444\mytext.txt
This obviously has the disadvantage that it will create unnecessary folders, but for my purpose it's not an issue.

Resources