J. L. Doty
J. L. Doty

Reputation: 41

Why does batch file wildcard ? not work, but * does

In a folder named ZipForCloudMaster I have a batch file and a zip file as follows:

ZipForCloudAll.bat
ZipForCloudMaster 2025-01-16_08-35-22.zip

The batch file zips the folder and its contents into a zip file named with the folder name and a date-time stamp. The zip file is then uploaded to a cloud folder for backup. But first, the batch file checks to see if any older zip files exist to warn me that if I proceed, I'll zip older zips into the zip for upload, which would cause a lot of bloat. For that I use the following code:

set "zipMask=ZipForCloudMaster ????-??-??_??-??-??.zip"
for %%A in (%zipMask%) do (
    REM echo %%~xA
    if /I "%%~xA"==".ZIP" (
        if !zcnt!==0 echo Zip files present:
        echo %%A
        set /a zcnt+=1
    )
)

and that doesn't work, apparently finding 0 zip files present with that zipMask signature. If I change the zipMask to:

set "zipMask=ZipForCloudMaster *.zip"

it works nicely, except it also catches other zips that don't match the mask containing the ? wildcard.

What am I doing wrong?

Upvotes: 1

Views: 43

Answers (2)

Magoo
Magoo

Reputation: 80173

I used a test directory :

 Directory of u:\your files\ZipForCloudMaster

17/01/2025  02:09    <DIR>          .
17/01/2025  02:09    <DIR>          ..
17/01/2025  02:16                 0 ZipForCloudAll.bat
17/01/2025  02:16                 0 ZipForCloudMaster 2025-01-16_08-35-22.zip
17/01/2025  02:16                 0 somezip.zip
17/01/2025  02:16                 0 anotherfile.xyz
17/01/2025  02:16                 0 1234-56-78_90-12-34.zip
               5 File(s)              0 bytes
               2 Dir(s)   3,214,053,376 bytes free

hence for the following batch, I started at u:\your files\ZipForCloudMaster to prove that the routine works where there are spaces in the directoryname.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION  

SET "sourcedir=u:\your files"
PUSHD "%sourcedir%\ZipForCloudMaster"
dir

set "zipMask=ZipForCloudMaster ????-??-??_??-??-??.zip"
SET /a zcnt=0

for %%A in (%zipMask%) do (
    REM echo %%~xA
    if /I "%%~xA"==".ZIP" (
        if !zcnt!==0 echo Zip files present:
        echo %%A
        set /a zcnt+=1
    )
)
ECHO --------------------%zipmask%-------------

set "zipMask=ZipForCloudMaster *.zip"
SET /a zcnt=0

for %%A in (%zipMask%) do (
    REM echo %%~xA
    if /I "%%~xA"==".ZIP" (
        if !zcnt!==0 echo Zip files present:
        echo %%A
        set /a zcnt+=1
    )
)
ECHO --------------------%zipmask%-------------

set "zipMask="ZipForCloudMaster ????-??-??_??-??-??.zip""
SET /a zcnt=0

for %%A in (%zipMask%) do (
    REM echo %%~xA
    if /I "%%~xA"==".ZIP" (
        if !zcnt!==0 echo Zip files present:
        echo %%A
        set /a zcnt+=1
    )
)
ECHO --------------------%zipmask%-------------

popd
GOTO :EOF

The point is that the filemask contains a space, which is a default separator, so the mask is interpreted as a list, ZipForCloudMaster and ????-??-??_??-??-??.zip or ZipForCloudMaster and *.zip.

In the first instance, only 1234-56-78_90-12-34.zip matches an element of the filemask, In the second, ZipForCloudMaster 2025-01-16_08-35-22.zip, somezip.zip and 1234-56-78_90-12-34.zip all match one of the list elements (*.zip)

So a solution is to "quote the string containing the space" as shown in the last example.

You might also find Using Boolean useful

Upvotes: 1

Swapnil Prakash
Swapnil Prakash

Reputation: 228

You should use a combination of dir with the /B flag and findstr

@echo off
setlocal enabledelayedexpansion

set "zipMask=ZipForCloudMaster ????-??-??_??-??-??.zip"
set "zcnt=0"

REM Use dir and pipe through findstr to handle the specific pattern
for /f "delims=" %%A in ('dir /b /a-d ^| findstr /r /i "^ZipForCloudMaster [0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]_[0-9][0-9]-[0-9][0-9]-[0-9][0-9]\.zip$"') do (
    if !zcnt!==0 echo Zip files present:
    echo %%A
    set /a zcnt+=1
)

if !zcnt!==0 (
    echo WARNING: Older zip files found. Proceeding will include these in the new zip.
) else (
    echo No older zip files found. Safe to proceed.
)

Upvotes: 0

Related Questions