I just want to echo a variable which is defined with ENABLEDELAYEDEXPANSION. It doesn't work.
Here's a small part of my long script on the issue
#echo off&setlocal enabledelayedexpansion
for /f "tokens=*" %%x in (%1) do (
set "D=%%x"
echo %%~nD
)
I have also written echo !~nD! but it doesn't work either.
my file (%1) only contains relative paths as so:
VENDOR\ford1.car
VENDOR\bmw.car
and my goal is to echoing 'ford1.car' or 'bmw.car' because I have to use them in the next steps of my script, that is only the file complete name.
Please some help and explanations. Thanks
Try:
#echo off&setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (%1) do (
echo %%~nxa
)
For only does substitution on the variable used in the for. You can't set a variable within and use substitution on it.
%%~na would only give you the file name without the extension. You have to use %%~nxa to get the file name and the extension.
If you want to set the file name to a variable and do something with each file, you have to use DelayedExpansion like this:
#echo off&setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (%1) do (
set d=%%~nxa
echo !d!
Do something with !d!
)
Or you could create a subroutine and not have to use a variable at all
#echo off&setlocal enabledelayedexpansion
for /f "tokens=*" %%a in (%1) do (
call :sub %%~nxa
)
goto :eof
:sub
%1 = your file name so do some processing on it.
Related
Hi I don't have much experience in batch-programming and have a problem. I have a .bat script that reads a file with a list of paths and i want to get the filename of these paths. I use the script in cygwin.
My code in the Script:
for /F %%a in (error1.txt) do (
set value=%%a
FOR /F %%I IN ("%value%") DO SET MYPATHFILE=%%~nxI
)
When i run the Script %value% is empty.
Value of error1.txt:
a/b/c/d/TextIWant
you need delayed expansion or you can directly use %%a:
for /F %%a in (error1.txt) do (
FOR /F %%I IN ("%%a") DO SET MYPATHFILE=%%~nxI
)
or
setlocal enableDelayedExpansion
for /F %%a in (error1.txt) do (
set value=%%a
FOR /F %%I IN ("!value!") DO SET MYPATHFILE=%%~nxI
)
It looks like you will need Delayed Expansion.
The current problem is, that you want to use a variable in the same set of brackets where you changed the value in (the surrounding For-Loop).
Add setlocal EnableDelayedExpansion to your code at the top and change the %value% to !value!
You can test the problem yourself with this code:
#echo off
setlocal EnableDelayedExpansion
set foo=bar
For /L %%a (1,2,1) do (
set foo=foobar
echo.old value %foo%
echo.new value !foo!
)
I hope it helped :)
Greetings
geisterfurz007
So, I have probably a simple question but I cannot seem to find an easy answer.
Issue: I have a file that contains a set of lines such as:
%windir%\file.exe
%windir%\file2.dll
and so forth...
What I am trying to do is echo the actual file path to a second file such that the resulting output would be something like:
C:\Windows\file.exe
C:\Windows\file2.dll
and so forth...
The actual source file could have other variables such as %programfiles% but all of them have a resulting actual path.
I am currently using a for /f loop but when I echo the variable, I just get the environment variable returned rather than the actual path to the file.
Is there a solution out there for batch scripting?
The actual script is below. Note I am all for making this more efficient as time to get the information is important.
#echo off
setlocal enabledelayedexpansion
reg.exe query "HKLM\System\CurrentControlSet\Services" >> registry_hklm_installed_services_tmp.txt 2>nul
reg.exe query "HKLM\System\ControlSet001\Services" >> registry_hklm_installed_services_tmp.txt 2>nul
reg.exe query "HKLM\System\ControlSet002\Services" >> %temp_outpath%\registry_hklm_installed_services_tmp.txt 2>nul
reg.exe query "HKLM\System\ControlSet002\Services" >> registry_hklm_installed_services_tmp.txt 2>nul
for /f "delims=?" %%a in (registry_hklm_installed_services_tmp.txt) do (
set regkey=%%a
call :getvalue
)
goto :parsereg
:getvalue
reg.exe query "!regkey!\Parameters" /v ServiceDll > nul 2>&1 && goto regkeyexist
goto :eof
:regkeyexist
for /f "tokens=2*" %%b in ('reg.exe query "!regkey!\Parameters" /v ServiceDll') do set ImagePath=%%c
call :regag
goto :eof
:regag
echo !ImagePath! >> registry_hklm_installed_services_tmp2.txt
goto :eof
:parsereg
for /f "delims=?" %%a in (registry_hklm_installed_services_tmp2.txt) do echo %%a >> registry_hklm_installed_services_tmp3.txt
You can use the for /f command to cycle through the lines in the file like you are doing, and pass the line from the file to a subroutine inside the batch file, which will resolve it while it is being passed. Give the following:
Test.txt
%windir%\test.txt
%programfiles%\Test2.txt
This batch file will resolve the environment variables:
#echo off
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=" %%i in (Test.txt) do call :Expand "%%i"
endlocal
goto TheEnd
:Expand
set _var=%1
echo !_var:"=!
:TheEnd
This is how the output looks when you run it:
c:\>Test.bat
C:\Windows\test.txt
C:\Program Files (x86)\Test2.txt
You can redirect the result to a new text file like this:
Test.bat > NewFile.txt
Or you can modify the original Test.bat to output the modified filename under Expand instead of echoing it to the console. It is important to include the quotes around %%i ("%%i") or spaces in the resolved paths will break into multiple variables when calling Expand (e.g., %1, %2, %3, etc.). The !_var:"=! removes the quotes.
This will also expand the variables.
#echo off
for /f "delims=" %%a in (Test.txt) do call echo %%a
pause
Test.txt
%windir%\test.txt
%programfiles%\Test2.txt
#ECHO OFF
SETLOCAL
FOR /f "delims=" %%a IN (q22726616.txt) DO (
FOR /f "delims=" %%b IN ('echo %%a') DO (
ECHO %%b
)
)
GOTO :EOF
I used a file named q22726616.txt containing your data for my testing.
[fixed following response - %%b line]
i need take paths from txt and get last folder name and then use it.
setlocal EnableDelayedExpansion
set InputFile=somar.txt
for /f "tokens=* delims=" %%x in ('Type "%InputFile%"') do (
set path=%%x
:shift
for /f "tokens=1* delims=\/" %%i in ( "!path!" ) do (
set folder=%%i
set path=%%j
)
if not [!path!] == [] goto :shift
echo folder: !folder!
)
endlocal
problem is that it works only for first line in txt. where is the problem?
You have a number of problems:
1) Your FOR loop is broken the moment you issue a GOTO. You will not get any more FOR loop iterations after GOTO. You could fix this by moving your GOTO loop into a subroutine and then CALL the subroutine from within your DO loop.
2) The PATH environment variable has a reserved meaning for Windows. You should never use that variable name for your own purposes, even if it is localized as you have it. It isn't worth tempting fate. Simply use a different variable name.
3) Perhaps not an issue with your data, but ! is a valid character for a file or folder name. Your expansion of FOR variables will corrupt names containing ! if delayed expansion is enabled. This can be fixed by toggling delayed expansion on and off as needed.
You also have a minor inefficiency - There is no need to use TYPE with your FOR loop. You can simply let FOR read the file directly. (unless the file is unicode)
You could take all the recommendations above, but there is a much simpler solution :-)
EDIT - change made to handle a path that ends with \
#echo off
set "InputFile=somar.txt"
for /f "usebackq eol=: delims=" %%A in ("%inputFile%") do (
for %%F in ("%%A\.") do echo folder: %%~nxF
)
The ~nx FOR variable modifiers directly give you the name and extension of the end of the path. Type HELP FOR from the command line to read about all the modifiers that are available to FOR variables.
For variable filenames:
#Echo OFF
:: By Elektro H#cker
set "File=File.ext"
Call :Get_paths "%InputFile%"
Pause&exit
:Get_paths
Set "AbsolutePath=%~dp1"
set "AbsolutePath=%AbsolutePath:\= %"
FOR %%# in (%AbsolutePath%) do (
Set "LastFolder=%%#"
Echo Folder: %%#
)
Echo Last Folder: %LastFolder%
GOTO:EOF
Output:
Folder: C:
Folder: Users
Folder: Administrador
Folder: Desktop
Last Folder: Desktop
For files:
#Echo OFF
:: By Elektro H#cker
set "File=test.txt"
For /F "Tokens=* usebackq" %%# in ("%FILE%") DO (
Set "AbsolutePath=%%~dp#"
Call set "AbsolutePath=%%AbsolutePath:\= %%"
CMD /Q /C "#FOR %%# in (%%AbsolutePath%%) do (Echo Folder: %%#)"
)
Pause&Exit
InputFile content must contains filename or folder.
ex)
D:\Test1 <= folder
D:\Test2\file.txt <= file
D:\Test3\01. folder <= folder but recognize file. that contain extension.
My code is:
SETLOCAL EnableDelayedExpansion
SET lastFolder=
SET InputFile=somar.txt
FOR /F %%F IN (%InputFile%) DO (
CALL :__GetFolderName "%%F"
#ECHO lastFolder: !lastFolder!
)
GOTO :EOF
:: ******************** Inner Batch
:__GetFolderName
IF "%~x1"=="" SET lastFolder=%~n1 & GOTO :EOF
SET dp=%~dp1
CALL :__GetFolderName "%dp:~0,-1%"
GOTO :EOF
:: ********************
ENDLOCAL
Result is:
lastFolder: Test1
lastFolder: Test2
lastFolder: Test3
i am trying to get files from a directory and want to set names of the file to a variable using batch script.
this is my code .but it always setting same value to variable
can any body give solution
echo on
setlocal EnableDelayedExpansion
for /f %%x in ('dir /b C:\backup_dir') do (
SET test=%%~nx
if "%test:~0,6%"=="kdc_db" (set DUMP=%%x)
if "%test:~0,6%"=="kdc_ke" (set KEYS=%%x)
)
echo %DUMP%
echo %KEYS%
here dump and keys variables are always set to same value
You need to use delayed expansion. You have already enabled it, you just need to replace your %'s with !'s
echo on
setlocal EnableDelayedExpansion
for /f %%x in ('dir /b C:\backup_dir') do (
SET test=%%~nx
if "!test:~0,6!"=="kdc_db" (set DUMP=%%x)
if "!test:~0,6!"=="kdc_ke" (set KEYS=%%x)
)
echo %DUMP%
echo %KEYS%
I've a batch script in which I loop trough all the filenames in a folder and then I invoke a command in order to remove the extension from the filename. I'd like to store at every iteration the filename (without extension) in a variable named result for later reuse.
The RemoveExtension function works fine. However I'm not able to retrieve the result and store it in the _result variable. When I print it, it's always empty. Thanks for your help!
#echo OFF
SETLOCAL EnableDelayedExpansion
set "_result="
for /f "delims=" %%i in ('dir "%~1\*.txt" /b') DO (
echo.filepath: "%~1\%%i"
call :RemoveExtension "%%i"
echo._result: "%_result%" // The "_result" variable is always EMPTY ""
)
goto :eof
:RemoveExtension
SETLOCAL
REM echo "%~1"
set "filename=%~1"
:loop
if "%filename:~-1%" NEQ "." (
set "filename=%filename:~0,-1%
goto :loop
)
set "filename=%filename:~0,-1%"
echo "%filename%"
ENDLOCAL & set "_result=%filename%"
goto :eof
Try this...much simpler way to remove the extension. Because you are changing _result inside a FOR loop, you need to access it using ! instead of %.
#ECHO OFF
SETLOCAL EnableDelayedExpansion
SET "_result="
FOR /f "delims=" %%i IN ('dir "%~1\*.txt" /b') DO (
ECHO.filepath: "%~1\%%i"
SET _result=%%~ni
ECHO._result: "!_result!"
)