1

I am writing a simple Windows batch script to (git) clone repositories. In it, I have an if statement that does not consistently branch:

  1 @echo off
  2 REM git clone a repo from M:\repo and the checkout the dev branch
  3 
  4 if [%1] EQU [] (
  5   echo Usage:
  6   echo clone.bat [name_of_repo] [optional: destination_path]
  7   goto EXIT
  8 )
  9 
 10 set dest_path="."
 11 set repo=%1%
 12 
 13 if NOT [%2] EQU [] (
 14     set dest_path=%2%
 15 )
 16 
 17 if NOT EXIST M:\repo\%repo% (
 18     echo Error: repository %repo% does not exist.
 19     goto EXIT
 20 )
 21 
 22 if NOT EXIST %dest_path% (
 23     echo Info: destination %dest_path% does not exist.
 24     set /p ans="Create path (Y/n)? "
 25     if "%ans%" == "Y" (
 26         goto RUN
 27     )
 28     echo Path not created. Done.
 29     goto EXIT
 30 )
 31 
 32 :RUN
 33 REM test that parameters are set
 34 echo %dest_path%
 35 echo %repo%
 36 
 37 :EXIT

(I inserted the line numbers to help the discussion. I hope they don't get in the way)

The script is very simple:

  1. Lines 4-8    : check that at least one argument is provided to the script
  2. Lines 10-15: set the name of the repository, and the optional destination path.
  3. Lines 17-20: exit if the repo doesn't exist
  4. Lines 22-30: are supposed to check that the destination path exists, and then prompt the user to create it, if it does not. This is where the problem is.

On line 24, set /p ans="Create path (Y/n)? ", I prompt to create the path and set the user's response to variable ans.

Then, if the response is "Y", the script would1 create the path and then go to RUN, otherwise it should exit.

When I run the script repeatedly as-is, I get this:

bcf@AVA-411962-1 E:\
$ clone gpsrx fake_path
Info: destination fake_path does not exist.
Create path (Y/n)? Y
Path not created. Done.

bcf@AVA-411962-1 E:\
$ clone gpsrx fake_path
Info: destination fake_path does not exist.
Create path (Y/n)? Y
fake_path
gpsrx

bcf@AVA-411962-1 E:\
$

I have tried many variations of the if statement. And, I have played with the setlocal EnableDelayedExpansion/setlocal DisableDelayedExpansion nonsense.

Can anyone point out what the problem is?

1I haven't added the mkpath %dest_path% yet (which would go between lines 25 and 25), since I don't want the script to actually do anything until it is working properly.

Blair Fonville
  • 908
  • 1
  • 11
  • 23
  • %1 is not the same as %1%. %2 is not the same as %2%. – Squashman Oct 12 '18 at 18:17
  • Best practice for doing comparisons with the `IF` command is to use quotes to surround the terms that are being compared. The brackets do not protect spaces in the terms that are being compared. – Squashman Oct 12 '18 at 18:18
  • When you are checking your `Y/N` answer you are inside a parentheses code block which means you need to enable delayed expansion with a `SETLOCAL` command and reference the variable with exclamation points instead of percent symbols. – Squashman Oct 12 '18 at 18:22
  • You should also for best practice always enclose file paths etc with doublequotes especially when their content is variable/user defined. When checking for the existence of a directory with `If Exist` you should have a trailing backslash on your directory name too! – Compo Oct 12 '18 at 18:23
  • @Compo Ok, Good tip, I've made the change (to my script, not here). Thanks. – Blair Fonville Oct 12 '18 at 18:25
  • @Squashman I tried adding `setlocal EnableDelayedExpansion` to various places within the parentheses and it didn't help. Also, I do have quotes surrounding the terms. The brackets are only use when I'm checking that the variables are empty (or only spaces, which would yield in the same results overall). – Blair Fonville Oct 12 '18 at 18:27
  • You do not have quotes surrounding the terms in all of your `IF` commands. I specifically mentioned BRACKETS. If you enable delayed expansion you also must reference the variable as `!ans!` as I stated in my previous comment. – Squashman Oct 12 '18 at 18:29
  • @Squashman Perfect, the `setlocal EnableDelayedExpansion` + `!ans!` worked! Care to make it an answer? – Blair Fonville Oct 12 '18 at 18:32
  • No because it is a duplicate question. Your issue gets asked at least a couple times a day. – Squashman Oct 12 '18 at 18:39
  • @Squashman I figured it must be. It's hard to search for though. I didn't think it was a variable problem; I thought it was `if` syntax. I was searching for the wrong thing. Thanks again. – Blair Fonville Oct 12 '18 at 18:39

1 Answers1

2

Here's some code for you to study?

@Echo Off
Rem git clone a repo from M:\repo and the checkout the dev branch

If "%~1"=="" (
    Echo Usage:
    Echo %~nx0 [name_of_repo] [optional: destination_path]
    Timeout 5 /NoBreak>Nul
    Exit /B
)

Set "repo="

If Exist "M:\repo\%~1\" (
    Set "repo=%~1"
) Else (
    Echo Error: repository %1 does not exist.
    Timeout 3 /NoBreak>Nul
    Exit /B
)

Set "dest_path="

If Not "%~2"=="" Set "dest_path=%~2"
If Not Exist "%~2\" (
    Echo Info: destination %2 does not exist.
    Choice /M "Create path"
    If ErrorLevel 2 (
        Echo Path not created. Done.
        Timeout 3 /NoBreak>Nul
    ) Else MD "%~2"
)

Rem test that parameters are set
Echo=%dest_path%
Echo=%repo%

Pause
Compo
  • 36,585
  • 5
  • 27
  • 39
  • That's fantastic. Thanks! I can improve a bunch of my scripts with this. The only (minor) issue is that the script continues even when the user opts to not create the directory, where it should exit instead. But that's a one-line fix. Thanks again. – Blair Fonville Oct 12 '18 at 19:05
  • @BlairFonville, you just need to replicate the previous `If/Else` loop and add a line `Exit /B` after the `Timeout` line but before the closing parenthesis. _I left it out because your script itself specifically said that the destination path was optional!_ – Compo Oct 12 '18 at 19:50
  • Yes, my wording was ambiguous. It is optional, and defaults to .\ if not provided. But if the user *does* provide a path, and the path doesn't exist, it may be that it doesn't exist because s/he mistyped. In which case, the option to create the directory is prompted, and if it was in fact mistyped, the user will want to cancel the operation. Long story, which I'm sure you care little about! Thanks again. – Blair Fonville Oct 12 '18 at 22:27
  • So, if I understand correctly @BlairFonville, you could simply change `Set "dest_path="` to `Set "dest_path=%__CD__:~,-1%"`. – Compo Oct 12 '18 at 23:29
  • Wow, I’ll try that. I will never fully understand Windows batch scripting. I really wish I was in a bash shell. – Blair Fonville Oct 13 '18 at 00:09