2

I'm building a script for Windows command line in which I try to check some filenames in a FOR loop, and then stripping off part of the filename into a variable for further use. Basically, what I want to happen is this:

  1. List all files in a certain directory, splitting of the extension like .osm.pbf in this case.
  2. Assign the filename to a variable.
  3. Out the last 7 characters of the filename in another variable.
  4. Compare this new variable to "-latest".
  5. If the compare is true, cut a part of the variable containing the filename.
  6. If the compare is false, take over the complete variable into another variable.

Through some trial and error and some searching online, I've arrived at this point (which still isn't doing what I want):

FOR /F "tokens=1-2 delims=." %%M IN ('DIR /b %VECTOR_WORKDIR%\*.osm.pbf') DO (
    SET VECTOR_CURRENT_MAP2=%%M
    ECHO !VECTOR_CURRENT_MAP2! >> %VECTOR_LOGFILE%
    SET LAST_BIT_TEMP=!VECTOR_CURRENT_MAP2:~-7!
    ECHO !LAST_BIT_TEMP! >> %VECTOR_LOGFILE%
    SET LAST_BIT=!LAST_BIT_TEMP: =! 
    ECHO !LAST_BIT! >> %VECTOR_LOGFILE%
    IF !LAST_BIT!=="-latest" ( 
      SET VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:~0,-8!
    ELSE
      SET VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2!
    )
    ECHO !VECTOR_CURRENT_MAP3! >> %VECTOR_LOGFILE%
)

This results in these lines in the log file, for the file basse-normandie-latest.osm.pbf:

basse-normandie-latest 
-latest 
-latest  
ECHO is on.

The first echo is correct, although the filename has a trailing space. (So actually it's "basse-normandie-latest ".)

The second echo doesn't seem to take this training space into account, as it correctly gives "-latest" as the last 7 characters. This echo also has a trailing space (So actually it's "-latest ".)

The third echo is an attempt to clear the spaces from the variable (by using ": ="), but this results in another trailing space. (So actually it's "latest ".)

The final echo after the IF statement (where I try to cut the "-latest" part from the filename), results in "ECHO is on".

I have SETLOCAL enabledelayedexpansion enableextensions declared at the top of my script.

Any thoughts on how to make this work, i.e. get rid of the trailing spaces to make the comparison work?

Thanks in advance for any pointers in the right direction!

Mofi
  • 46,139
  • 17
  • 80
  • 143
Repeat64
  • 31
  • 3
  • 2
    [Debugging your batch files](http://www.robvanderwoude.com/battech_debugging.php). – JosefZ Jun 26 '16 at 09:15
  • 1
    What is it not doing exactly? `I've arrived at this point (which still isn't doing what I want):` is hardly enough to know what it doesn't do. And try not to reply to me in a comment, but edit your question. – Dennis van Gils Jun 26 '16 at 10:50

1 Answers1

0

A line like

ECHO !VECTOR_CURRENT_MAP2! >> %VECTOR_LOGFILE%

results in appending the value of the environment variable VECTOR_CURRENT_MAP2 to file with file name stored in environment variable VECTOR_LOGFILE with a trailing space because there is a space before redirection operator >> which is interpreted by Windows command processor as part of the string to output by command ECHO. This space must be removed to get the file name redirected into the log file without a trailing space.

In general it is critical on redirecting a variable string into a file without a space between the variable string and the redirection operator in case of the variable string ends with a space and a number being a valid handle number like  1 or  2 or  3. There are several solutions to workaround this problem like specifying the redirection left to command ECHO, i.e.

>>%VECTOR_LOGFILE% ECHO !VECTOR_CURRENT_MAP2!

But on using delayed expansion as simply necessary here, it is safe to append the redirection at end without a space between exclamation mark and >>, i.e.

ECHO !VECTOR_CURRENT_MAP2!>> %VECTOR_LOGFILE%

The space after redirection operator is ignored by Windows command processor and therefore can be kept although many batch file programmers (like me) with good syntax highlighting don't insert a space after a redirection operator.

On comparing strings with command IF and enclosing one string in double quotes which is always a good idea, it must be made sure that the other string is also enclosed in double quotes. The command IF does not remove the double quotes before comparing the strings. The double quotes are parts of the compared strings.

The condition

IF !LAST_BIT!=="-latest"

is only true if the string assigned to environment variable LAST_BIT would be with surrounding quotes which is never the case with your batch code and therefore the condition is never true.
Correct would be:

IF "!LAST_BIT!"=="-latest"

There is no need to use command DIR to search for files with a pattern in a directory as command FOR is designed for doing exactly this task. Processing of output of command DIR is an extension of FOR available only if command extensions are enabled as by default.

The file extension is defined by Microsoft as everything after last dot in name of a file. Therefore the file extension for your files is pbf respectively .pbf and .osm belongs to the file name.

Command FOR offers several modifiers to get specific parts of a file or directory name. Those modifiers are explained in help output into console window on running in a command prompt window for /?. Help of command CALL output with call /? explains the same for processing parameters of a batch file or subroutine (batch file embedded within a batch file).

Your code with all mistakes removed:

FOR %%M IN (*.osm.pbf) DO (
    SET "VECTOR_CURRENT_MAP2=%%~nM"
    SET "VECTOR_CURRENT_MAP2=!VECTOR_CURRENT_MAP2:~0,-4!"
    ECHO !VECTOR_CURRENT_MAP2!>>%VECTOR_LOGFILE%
    SET "LAST7CHARS=!VECTOR_CURRENT_MAP2:~-7!"
    ECHO !LAST7CHARS!>>%VECTOR_LOGFILE%
    IF "!LAST7CHARS!" == "-latest" ( 
        SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:~0,-7!"
    ) ELSE (
        SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2!"
    )
    ECHO !VECTOR_CURRENT_MAP3!>>%VECTOR_LOGFILE%
)

Easier would be using this code with using string substitution feature of command SET, i.e. search within a string case-insensitive for all occurrences of a string and replace them with another string which can be also an empty string.

FOR %%M IN (*.osm.pbf) DO (
    SET "VECTOR_CURRENT_MAP2=%%~nM"
    SET "VECTOR_CURRENT_MAP2=!VECTOR_CURRENT_MAP2:~0,-4!"
    ECHO !VECTOR_CURRENT_MAP2!>>%VECTOR_LOGFILE%
    SET "VECTOR_CURRENT_MAP3=!VECTOR_CURRENT_MAP2:-latest=!"
    ECHO !VECTOR_CURRENT_MAP3!>>%VECTOR_LOGFILE%
)

%%~nM is replaced on execution by Windows command processor by the name of the file without drive, path and file extension resulting for your example in basse-normandie-latest.osm.

The unwanted file name part .osm is removed with the next line in both batch code blocks which chops the last 4 characters from the file name string.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • for /?
  • if /?
  • set /?

Read the answer on question Why is no string output with 'echo %var%' after using 'set var = text' on command line? for an explanation why I used set "variable=value" on every line which assigns a value string to an environment variable because trailing whitespaces are critical for your task.

Community
  • 1
  • 1
Mofi
  • 46,139
  • 17
  • 80
  • 143
  • That were a lot of good pointers! Thanks for your time and effort, I'll adjust the code accordingly and read up on the items tyou suggested. – Repeat64 Jun 26 '16 at 18:25