Home > Enterprise >  Command prompt FOR /F %%f IN ('DIR /B') fails for first result
Command prompt FOR /F %%f IN ('DIR /B') fails for first result

Time:11-25

I am using a batch file to rename all files in a folder into a numbered list. The code I use is as follow:

set /a Index=1

setlocal enabledelayedexpansion

for /f "tokens=*" %%f in ('dir /b') do (
echo %%f
echo !Index!
rename "%%f" "!Index!.*"
set /a Index =1
pause
)

The result of the batch file is

G:\Directory A> (
echo
03.jpg
echo 1
rename "
03.jpg" "1.*"
set /a Index =1
pause
)

03.jpg
1
The filename, directory name, or volume label syntax is incorrect.
Press any key to continue . . .

G:\Directory A> (
echo 04.jpg
echo 1
rename "04.jpg" "1.*"
set /a Index =1
pause
)
04.jpg
1

The first result ALWAYS contains a line break at the beginning of the file name, which causes the RENAME command to fail. Can anyone tell me what is wrong with my code?


UPDATE

There is the folloging auto-run code set up in the Windows registry:

[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"Autorun"="@chcp 65001>nul & prompt $d$s$s$t$_$p$g & cls"

CodePudding user response:

After digging a bit with my batch file, I recognized that this is a problem with the Autorun option that I had set ages ago in Registry that look like this:

[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"Autorun"="@chcp 65001>nul & prompt $d$s$s$t$_$p$g & cls"

Apparently the CLS command caused the weird line break to happen. After removing the CLS part from Autorun, the batch file works as it is intended to.

CodePudding user response:

The finding described in the self-answer is very interesting albeit tremendously nasty!

The auto-run code contains the cls command, which sends a single form-feed character (FF, code0x0C) to the console that tells it to clear the screen (the character can be displayed by running cls > con in the console).

When executing cls within a for /F loop, the FF is captured: for /F %F in ('cls') do @echo/%F in the command prompt displays that character.

A for /F loop initiates a new cmd.exe instance to execute the given command line; this is done by preceding cmd /C to the command line.

With auto-run commands set up, they become executed within the for /F loop (due to the unfortunate lack of the /D option, which would prevent them to run).

The auto-run command line from the question has got cls involved, so for /F %F in ('rem') do @echo/%F captures a FF, even though the actual command rem does not return anything.


There are methods to suppress the FF character (note that the following code examples are intended to be placed in a rather than entered into the console):

  1. Precede the desired command line by echo/& to append a line-break to a potential FF to have an extra line at the beginning and skip that line by for /F:

    rem // Precede the desired command with `echo/` and skip the first line:
    for /F "skip=1 delims=" %%I in ('echo/^& dir /B') do echo "%%I"
    
  2. Retrieve a FF first and define it as the eol (end of line) character for for /F, then again prefix the desired command line with echo/& just like before:

    rem // Retrieve the form-feed character and ignore lines beginning with a form-feed:
    for /F delims^=^ eol^= %%F in ('echo/^& cls') do set "_FF=%%F"
    
    rem // Precede the desired command with `echo/` and use form-feed as `eol` character:
    for /F "delims= eol=%_FF%" %%I in ('echo/^& dir /B') do echo "%%I"
    
  • Related