1

I'm using REN to find files with a certain naming pattern and modify them, like so:

REN "?%var1%?%var2%.S16" "?%var1%?%var3%.S16"

This finds all files like aXaY.S16, bXaY.S16, cXbY.S16 (etc) and renames them to aXaZ.S16, bXaZ.S16, cXbZ.S16 (etc). If it finds what it's looking for, it works just fine. But there's a problem: REN won't halt the operation if it encounters an error.

To prove this is the case, my script is as follows:

@echo off
set /p var1=Enter first var: 
set /p var2=Enter second var:
set /p var3=Change second var to:

echo Searching for all files matching ?%var1%?%var2%.S16

REN "?%var1%?%var2%.S16" "?%var1%?%var3%.S16"
echo Errorlevel: %errorlevel%
IF ERRORLEVEL 1 goto :FAIL
echo Success!
PAUSE
goto :eof

:FAIL
echo I done goofed!
PAUSE
exit

I ran this in a folder containing a few hundred files. I searched for files matching ?0?a.S16 (of which there are ~40 results) and asked it to change the 'a' to a 'c', knowing that files with this name already exist and should create a conflict.

Here is the console output (shortened for brevity):

Enter first var: 0
Enter second var:a
Change second var to:c
Searching for all files matching ?0?a.S16
A duplicate file name exists, or the file
cannot be found.
A duplicate file name exists, or the file
cannot be found.
A duplicate file name exists, or the file
cannot be found.
...(etc)...
Errorlevel: 1
I done goofed!
Press any key to continue . . .

The complaint about duplicates goes on for about 40 lines, as expected. As you can see, though, Errorlevel returns 1 at the end of the process instead of quitting at the first sign of trouble, which is what I'd rather it do.

I did consider passing this through FOR /f but I don't know how I would also pass the searchmask through it. I know FOR supports '*' wildcards, but as far as I'm aware, it doesn't support '?' the same way REN does. A possible alternative would be to use regular expressions somehow, but I can't wrap my head around them at all despite trying.

Any clues? Many thanks for taking a look.

Vika Marquez
  • 353
  • 1
  • 3
  • 12
  • You've got a confusing situation. `%errorlevel% is not the same as `errorlevel`. The first is a new local variable named `errorlevel`, the second is the built in `ERRORLEVEL`. The value of the first does not necessarily match the value of the second, because they're not the same. – Ken White Jan 28 '16 at 04:16
  • Noted, thank you for the info. But the script is ultimately checking ERRORLEVEL, so despite the mistake (that echo was just intended as debug output and can be omitted), the problem remains the same. – Santiago PS Jan 28 '16 at 04:25
  • @KenWhite: As far as I know, the value of `errorlevel` variable is the same used in `if errorlevel` command. Could you post an example where these two values does not match? I am very interested in this topic in order to keep precise the information at [this post](http://stackoverflow.com/questions/34987885/what-are-the-errorlevel-values-set-by-internal-cmd-exe-commands/34987886#34987886). TIA – Aacini Jan 28 '16 at 04:45
  • @KenWhite - As long as no one explicitly defines a user defined ERRORLEVEL variable, then the OP's code is just fine. `%ERRORLEVEL%` will preferentially expand to a user defined environment variable value, and will default to the desired ERRORLEVEL value only if the environment variable is not defined. – dbenham Jan 28 '16 at 04:58

2 Answers2

1

Yes, you have documented how the REN command works - it continues to completion, even after a rename fails, and then reports ERRORLEVEL 1 if at least one rename failed.

If you want to halt processing upon the first error, then you will have to write your own loop to rename each file, one at a time. You should not use the simple FOR loop because it can begin iterating before it has scanned the entire directory, so you run the risk of renaming the same file twice. The safe thing to do is use FOR /F coupled with DIR /B /A-D instead.

@echo off
set /p var1=Enter first var: 
set /p var2=Enter second var:
set /p var3=Change second var to:

echo Searching for all files matching ?%var1%?%var2%.S16

for /f "eol=: delims=" %%F in (
  'dir /b /a-d "?%var1%?%var2%.S16"'
) do ren "%%F" "?%var1%?%var3%.S16" || goto :break
:break
echo Errorlevel: %errorlevel%
IF ERRORLEVEL 1 goto :FAIL
echo Success!
PAUSE
goto :eof

:FAIL
echo Errorlevel: %errorlevel%
echo I done goofed!
PAUSE
exit

Note - The wildcard rules used by REN are not at all intuitive. You should have a look at How does the Windows RENAME command interpret wildcards? to make sure you are getting the results you expect.

Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
0

replace you ren command with

FOR /f "delims=" %%x IN ('dir /b /a-d "%sourcedir%\?%var1%?%var2%.S16" 2^>nul') DO REN "%sourcedir%\%%x" "?%var1%?%var3%.S16"&IF ERRORLEVEL 1 ECHO failed AT %%x&goto :EOF 

note This is a direct patch of my test, where I set sourcedir to a testing directory. In your case, you'd need to make appropriate adjustments.

This makes a directory list in basic form without directories and each filename is then assigned to %%x Then rename is then attempted and the resultant errorlevel interpreted. On fail, show the name for good measure and bail out.

[edit] 2^>nul added into dir command.

This will cause dir errors (like "file not found") to be directed to nowhere. The caret (^) is required to tell cmd that the > is part of the dir command, not the for.

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • Thank you for your help. When I run this for files I know it won't find, it gives me generic "File Not Found" errors, but doesn't specify what it failed to find and Errorlevel reports 0. It only seems to perform the echo if a file name conflict exists (i.e. it found the files I asked for, but couldn't rename them). – Santiago PS Jan 28 '16 at 06:11