3

This could possibly a duplicate of several questions out there in the SO, dostips and ss64. The research I've done point me to look out for _scope_ in functions. but my solutions is simple and straight forward but still problem exists

  1. what is really behind the SETLOCAL and ENDLOCAL
  2. How contextworkd in batch scripts ex (goto) 2>nul
  3. Why (goto) wrapped in braces (explained in dostips)

Here is the code i've written so far to copy file from one place to another. My Goals were:

  • Research the scope and contextof batch script
  • code reuse
    @echo off
    setlocal EnableDelayedExpansion
    goto :main

:main
    setlocal
    set _app=test
    set _base=C:/wamp64/www
    set _destination=!_base!/test
    set _source=%~dp0%/build
    set /A _flag=0

    echo *********************************************
    echo    Deploying in %~1 mode: %TIME%
    echo        Deploy path: !^_destination!
    echo *********************************************

    call :check !_base!, !_app!, _flag
    if !_flag!==0 (
        call :create !_base!, !_app!
    )
    xcopy "!_source!" "!_destination!" /D /C
    exit /b 0
    endlocal

:setbase 
    echo ::::: setting up base :::::
    chdir /D C:

    rem the base dir for app to exists=> %1
    chdir %~1 
    exit /b 0

:check 
    echo ::::: checking for local web server destination :::::
    call :setbase %~1

    set %~3= dir /p|find /C "%~2"
    exit /b 0

:create 
    echo ::::: creating the app folders :::::

    rem setting the base to create app folder %1
    call :setbase %~1
    mkdir %~2
    exit /b 0

endlocal

This is the output i get when i initiate deploy.bat

*********************************************
   Deploying in production mode: 19:28:53.13
       Deploy path: C:/wamp64/www/test
*********************************************
::::: checking for local web server destination :::::
::::: setting up base :::::
0
::::: creating the app folders :::::
::::: setting up base :::::
A subdirectory or file test already exists.

seems like the If !_flag!==0 which is checking whether the app folder exist in the server root and is not working at all. When i learnt the way to pass parameters to other functions; i thought it as passing a pointer like reference but it looks like it is deeply tied to scope. So what's going on here in the code.

2
  • 1
    In :check, you are aren't actually running the command when you set _flag, you're setting that variable to the literal string. Use for /F to store command output in a variable. Commented Dec 20, 2018 at 14:54
  • 1
    Note that it is %~dp0, not %~dp0%! Commented Dec 20, 2018 at 14:54

1 Answer 1

3

Checking for File/Dir Existence

The code you're employing to verify that a directory (?) exists is

set %~3= dir /p|find /C "%~2"

I don't think this is doing what you intend. SET /P is often used like this in order to pipe the output of a command into an environment variable. (Though, you are giving /P to dir, which paginates the output—probably not what you intended.) The command you have won't do that, though. I'd guess that what this is accomplishing is setting the var to (literally) " dir /p" and then piping that through find-count. That results of find.exe /C never make it back into the envvar though. The output line "0" is the result of piping (nothing) through find.exe /C.

I propose a simpler test for existence:

IF EXIST "%~2" (SET /A %~3=1) ELSE (SET /A %~3=0)

This test worked on my Win10 machine.

I have seen some variance in how IF EXIST works. If you didn't want to use that, you could do it with a FOR loop.

FOR /F "tokens=*" %%e IN ('DIR /B') DO IF "%%~e"=="%~2" SET /A %~3=1

If you want to use the pipe in the FOR command, you'll have to escape it.

FOR /F "tokens=*" %%e IN ('DIR /B ^| find /C "%~2"') DO SET /A %~3=%%~e

All three of these methods worked for me.

SETLOCAL

I do not think there exists an official reference guide for cmd syntax other than the built-in help (SETLOCAL /?)

My experience with it is that it pushes all the envvars and working directories onto a "stack" and a corresponding ENDLOCAL or EXIT (though in scripts, you almost always want to use EXIT /B) will pop the environment off that "stack." In effect, it means that envvar/CWD changes you make in a SETLOCAL will only be temporary.

Sign up to request clarification or add additional context in comments.

2 Comments

though in scripts, you almost always want to use EXIT /B. This is because if exist /b is not defined at the end of the function, the usual execution flow will continue which is top to bottom and can eventually be end up in a recursion with max recursion depth reached.
This trick IF EXIST "%~2" (SET /A %~3=1) ELSE (SET /A %~3=0) solved the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.