0

Greetings fellow mortals! I will cut right through it.

What I am trying to achieve & how it works


I am currently trying to create a simple batch-script which iterates through files in a source directory, validates the file extension and count the file size of each file with the right extension, which in this case is .xml.

Upon checking for these conditions, the files will be moved to their respective directory.

What I've tried so far


While doing the first condition of checking the file extension, my logic seems to be flawed. (explained after the code block.) I am not used to creating scripts in batch and therefore not entirely used to the syntax - but I hope it's correct!

I've kept the echo's as a debug reference for the output later in this post.

@ECHO OFF
SETLOCAL
SET "sourcedir=C:\lorem\ipsum"
SET "destdir=C:\foo\bar"

FOR %%G IN ("%sourcedir%\*") DO (
    IF NOT "%%~nxG"=="*.xml" (
        echo %%~nxG
        ::echo (MOVE "%%G" "%destdir%\not-accepted")
        echo "move file to \not-accepted"
    ) ELSE (
        FOR %%i in ("%sourcedir%\*.xml") DO (
            @set count=%%~zi
            echo "%count%"
            IF "%count%" LEQ 200 (
                echo "move file to \empty-pba"
            ) ELSE (
                echo "move file to \import"
            )
        )
    )
)
pause

The first statement never seem to give a false condition, despite having file extensions that doesn't match the condition and therefore does not continue to the next for-loop, meaning the allowed file extension is always moved to the \not-accepted folder.

The output is as follows:

lorem.xml
"move to \not-accepted"
foo.pdf
"move to \not-accepted"
ipsum.xml
"move to \not-accepted"
bar.pdf
"move to \not-accepted"

My initial question


Is my logic flawed here? My first bet is that I've probably messed up the if-statement somehow, either syntax error or that I've completely missed on the logic here. Am I doing something illegal?


The time you've already spent reading this and the help is already greatly appreciated! <3

Sanguinary
  • 354
  • 2
  • 3
  • 16
  • 1
    `*` does not belong in the statement `IF NOT "%%~nxG"=="*.xml"` – T3RR0R Apr 09 '21 at 09:44
  • @T3RR0R Thank you! I did not take into consideration that `if` statements does not accept pattern matching. Would the better approach be to use `/f delims=` to get the extension and store the extension as a variable to be used in the statement? – Sanguinary Apr 09 '21 at 09:56
  • 1
    drop the `n` and just use the `x` extension modifier: `IF NOT "%%~xG"==".xml"` – T3RR0R Apr 09 '21 at 10:02
  • Embarassing. I should have double-checked the modifiers, my bad. Thank you so much for the help, this solved my issue. You may leave an answer for some additional internet points if you'd like. :) – Sanguinary Apr 09 '21 at 10:14
  • 2
    I would also add the `/i` switch to make the `if` statement case insensitive, just incase someone decided to give the extension `.XML` instead of `.xml` so do `if /i not "%%~xG" == ".xml"` You are welcome to test it from `cmd` as `if not ".XML" == ".xml" echo not xml` vs `if /i not ".XML" == ".xml" echo not xml` – Gerhard Apr 09 '21 at 10:22
  • @Gerhard Clever suggestion, didn't think about that *case*. (pun intended) Much appreciated, thanks! – Sanguinary Apr 09 '21 at 10:27
  • Your question statement suggested you were wanting to count the number of characters in each file, but your code is providing only the file size. That would only work if your XML files use only single byte ASCII characters, and no BOM, but XML uses Unicode, usually UTF-8, can include a BOM, and may therefore use from 2, to 4 bytes per character, for those over U+007F, _(2 bytes for U+0080..U+07FF, 3 bytes for U+0800..U+FFFF, and 4 bytes for U+10000..U+10FFFF)_. Could you please explain, whether you really want a character count? or just a file size? – Compo Apr 09 '21 at 11:19
  • @Compo Nice observation! You're right. When I started on this earlier today I initially wanted to count the **characters** of the file - but changed this to the **file size** (more convenient for my case) after I wrote the introduction to the question. I've edited the question to reflect the code provided. Thanks for new information about the charset XML uses, did not know this. – Sanguinary Apr 09 '21 at 12:00
  • Also your `count` variable needs [delayed expansion](https://stackoverflow.com/questions/30282784/variables-are-not-behaving-as-expected/30284028#30284028). – Stephan Apr 09 '21 at 13:38
  • I am confused as to why you have nested `FOR` commands? The `FOR` and `IF..ELSE` commands are all you need. And because you have nested `FOR` commands, you are iterating the entire source FOLDER multiple times which is super inefficient for large folder structures. – Squashman Apr 09 '21 at 14:10

1 Answers1

0

Maybe I am not fully understanding what you are trying to accomplish but it seems like your code is doing way more than it has to. You should not need the nested FOR commands to accomplish this task. You are already iterating the folder so there is no need to do it again.

@ECHO OFF
SETLOCAL
SET "sourcedir=C:\lorem\ipsum"
SET "destdir=C:\foo\bar"

FOR %%G IN ("%sourcedir%\*") DO (
    IF /I NOT "%%~xG"==".xml" (
        echo %%~xG
        REM echo (MOVE "%%G" "%destdir%\not-accepted")
        echo "move file to \not-accepted"
    ) ELSE (
        echo File SIZE %%~zG"
        IF %%~zG LEQ 200 (
            echo "move file to \empty-pba"
        ) ELSE (
            echo "move file to \import"
        )
    )
)
pause
Squashman
  • 13,649
  • 5
  • 27
  • 36
  • Yup! I noticed I iterated the same folder twice, got it fixed right after @Gerhard corrected my modifier. This would be the working solution indeed. Forgot to edit my question. – Sanguinary Apr 13 '21 at 20:07