3

I have a question how to set multiple files as variables in batch file? I trying to do something with below script:

move c:\*.gpg q:\
for %%F in ("q:\*.gpg") do (set file=%%~nxF)
if exist q:\*.gpg echo done copying files: %file%

Above works fine only with one file. If there are more than two it only echos one of them. How can I echo in one line all the files that where copied?

phuclv
  • 37,963
  • 15
  • 156
  • 475
geminatores
  • 53
  • 1
  • 2
  • 6
  • 2
    First you should group both your commands: `set` and `if` in the same block (to be both executed by each `for` iteration). Second, it seems a [Delayed Expansion](http://ss64.com/nt/delayedexpansion.html) problem. Check [this post](http://stackoverflow.com/questions/10558316/example-of-delayed-expansion-in-batch-file) or [this one](http://stackoverflow.com/questions/22278456/enable-and-disable-delayed-expansion-what-does-it-do) (or tons of others revealed by _Google_-ing). – CristiFati Aug 12 '16 at 10:52

2 Answers2

5

There are multiple problems with your code

for %%F in ("q:\*.gpg") do (set file=%%~nxF)
if exist q:\*.gpg echo done copying files: %file%

First, you're assigning new values to the variable file each loop and then overwriting it every time without doing anything. Therefore after the loop file will only contain the value in the last loop. Move the echo part to inside the loop instead

Another problem is that variables are expanded at parse time by default. You need to enable delayed expansion and use ! instead of % to make it expand at runtime

Setlocal EnableDelayedExpansion
for %%F in ("q:\*.gpg") do (
    set file=%%~nxF
    echo done copying file: !file!
)

If you want to echo all files at once then set the file variable to contain the list of files

for %%F in ("q:\*.gpg") do (
    set file=!file!, %%~nxF
)
echo done copying files: %file%

The file existence check is redundant. You can check the exit code after moving and exit if the files weren't moved.

phuclv
  • 37,963
  • 15
  • 156
  • 475
2

The variables are not constant so remember to activate the expansion delayed variable, here the expansion of the variable file must be delayed.

Delayed Expansion will cause variables to be expanded at execution time rather than at parse time, this option is turned on with the SETLOCAL command. When delayed expansion is in effect variables can be referenced using !variable_name! (in addition to the normal %variable_name% )

Delayed variable expansion is often useful when working with FOR Loops, normally an entire FOR loop is evaluated as a single command even if it spans multiple lines of a batch script. This is the default behaviour of a FOR loop:

Example :

@echo off
setlocal
:: count to 5 storing the results in a variable
set _tst=0
FOR /l %%G in (1,1,5) Do (echo [%_tst%] & set /a _tst+=1)
echo Total = %_tst%


C:\> demo_batch.cmd
[0]
[0]
[0]
[0]
[0]
Total = 5

Notice that when the FOR loop finishes we get the correct total, so the variable correctly increments, but during each iteration of the loop the variable is stuck at it's initial value of 0

The same script with EnableDelayedExpansion, gives the same final result but also displays the intermediate values:

@echo off
setlocal EnableDelayedExpansion 
:: count to 5 storing the results in a variable
set _tst=0
FOR /l %%G in (1,1,5) Do (echo [!_tst!] & set /a _tst+=1)
echo Total = %_tst%

C:\> demo_batch.cmd
[0]
[1]
[2]
[3]
[4]
Total = 5

Notice that within the for loop we use !variable! instead of %variable%.

And your batch script can be written like that :

@echo off
Set "Ext=*.gpg"
set /a Count=0
Setlocal EnableDelayedExpansion
for %%F in ("q:\%Ext%") do (
    SET /a Count+=1
    set "file=%%~nxF"
    echo Done copying file [!Count!] : !file!
)
SET /a "COUNT_TOT=%Count%"
ECHO.
ECHO Total of [%EXT%] files(s) : %Count% file(s)
pause
Hackoo
  • 18,337
  • 3
  • 40
  • 70