0

I am trying to make a batch files that:

  • finds all folders that contain a specific file (_extern.inf) <- WORKING
  • Check that the folder name contains exactly X number of a delimiter. Otherwise ignore file (i.e. if the folder name is not the expected format ignore the folder) <-- NOT WORKING
  • Splits the folder name by a delimiter and uses one of the substrings to make the path to move the folder to <- WORKING

I have everything working except for the check. I have seen Batch File Count all occurrences of a character within a string but it doesn't seem to work for me (%count% is empty). I guess because of the nested for loop. It also seems that breaking the loop for files that don't conform is not trivial...

It is %%~ni that I would like to check if contains %expect_delims% occurrences of %delim%. If not continue to next folder.

@echo off
REM No trailing spaces!
set "infolder=input_path"
set "outfolder=output_path"
set "delim=_"
set "expect_delims=2"


REM Resursively look for folders with _extern.inf files
for /d /r "%infolder%" %%i in (*) do  @if exist %%i\_extern.inf (

    REM echo the folder is %%i


    REM tokens decide which part to take of the split string.
    REM "tokens=1,3" would take first and third and make %%b available

    for /F "tokens=1 delims=%delim%" %%a in ("%%~ni") do (

        REM Create project folder if doesn't exist
        if not exist "%outfolder%\%%a.raw\Data\" (
            echo creating folder %outfolder%\%%a.raw\Data
            mkdir "%outfolder%\%%a.raw\Data"
        )

        REM move folder if doesn't exist
        if exist "%outfolder%\%%a.raw\Data\%%~nxi" echo raw folder already exists!

        if not exist "%outfolder%\%%a.raw\Data\%%~nxi" (
            echo Moving "%%~fi" to "%outfolder%\%%a.raw\Data\%%~nxi"
            move "%%~fi" "%outfolder%\%%a.raw\Data\%%~nxi"
        )
    )

)
Jan Stanstrup
  • 1,152
  • 11
  • 28
  • 1
    Put the code to count the number of delimiters into a sub-routine, call it by [`call`](https://ss64.com/nt/call.html), and try again; if you place it in your loop `%count%` will not update (unless you enable [delayed expansion](https://ss64.com/nt/delayedexpansion.html) and write `!count!`)... – aschipfl Jun 13 '19 at 15:48
  • 1
    Instead of counting the number of delimiters you could just do this: `for /F "tokens=1-4 delims=_" %%a in ("%%~ni") do if "%%c" == "" (echo Too few delimiters!) else if not "%%d" == "" (echo Too many delimiters!)` (assuming that it is fine to collapse adjacent delimiters into one)... – aschipfl Jun 13 '19 at 15:57
  • Thanks for the suggestions @aschipfl. I liked the simplicity of the last one. But I am having trouble making it work. I wanted to make it possible to put how many delimiters to expect. So I need to select which tokens to look at (unless there is some trick I am missing). I tried to calculate the token numbers but I cannot seem to pass that to the next for loop. – Jan Stanstrup Jun 14 '19 at 12:00
  • You can set the `tokens` option by a variable (just like you do for `delims`), but make sure to use immediate (`%`) expansion for that variable (or an argument of a sub-routine, like `%~1`)... – aschipfl Jun 14 '19 at 12:06
  • so `tokens=1,%start_char%,%end_char%`? But they are empty if I do that... I guess I am missing some trick... – Jan Stanstrup Jun 14 '19 at 12:10
  • Ohh. found a way to transport the vars past the block based. I edited the question. Feel free to post the solution if you want. If you think something can be done smarter even better. But thank you very much for the help. All working now. – Jan Stanstrup Jun 14 '19 at 13:26
  • You're welcome! Instead of adding the solution to the question, let me recommend to post it as an answer (which you could even accept then later)... – aschipfl Jun 14 '19 at 14:17
  • As batch processing is quite heavily readable, even if you get it to work, it will be veryf difficult to maintain. Why don't you opt for another language, like Perl or Python for this? – Dominique Jun 14 '19 at 14:21
  • @aschipfl yes will do. Just wanted to give you a chance to get the credit. – Jan Stanstrup Jun 14 '19 at 15:51
  • @Dominique because this needs to run on a computer controlling a scientific instrument so introducing another language makes it less easy for others to install and use and these systems are notoriously intolerant to changes (windows update typically required off etc) so didn't want to have to install anything. This is in fact moving the data away to be reachable by other machines doing data analysis in R where I am comfortable writing decent code ;) With this working I will be happy if I don't need to do batch scripting again for some years... – Jan Stanstrup Jun 14 '19 at 15:51

1 Answers1

1

Based on the ideas of @aschipfl I found a way to make it work.

Transporting the variables across block boundaries is based on this: Windows batch setlocal enabledelayedexpansion call return value

@echo off

REM ****** SETTINGS ******
REM No trailing spaces!
set "infolder=input_dir"
set "outfolder=output_dir"
set "delim=_"
set "expect_delims=4"


REM SCRIPT STARTS HERE
setlocal
set /a "token_start=%expect_delims%+1"
set /a "token_end=%expect_delims%+2"


REM Resursively look for folders with _extern.inf files
for /d /r "%infolder%" %%i in (*) do  @if exist %%i\_extern.inf (

    echo ****** Start processing ******
    echo File: "%%~i"


    for /F "tokens=1,%token_start%,%token_end% delims=%delim%" %%a in ("%%~ni") do (
        REM echo the raw folder is %%i
        if "%%b" == "" (echo Filename check: Too few delimiters. File ignored.) else (
            if not "%%c" == "" (echo Filename check: Too many delimiters. File ignored.) else (

                echo Filename check: OK

                REM Create project folder if doesn't exist
                if not exist "%outfolder%\%%a.raw\Data" (
                    echo creating folder "%outfolder%\%%a.raw\Data"
                    mkdir "%outfolder%\%%a.raw\Data"
                )

                REM move raw folder if doesn't exist
                if exist "%outfolder%\%%a.raw\Data\%%~nxi" echo raw folder already exists! File ignored.

                if not exist "%outfolder%\%%a.raw\Data\%%~nxi\" (
                    echo Moving "%%~fi" to "%outfolder%\%%a.raw\Data\%%~nxi"
                    move  "%%~fi" "%outfolder%\%%a.raw\Data\%%~nxi"
                )

            )    
        )

        echo ****** End processing ******
        echo.
    )



)
Jan Stanstrup
  • 1,152
  • 11
  • 28