Writing a Batch Program from Local System Variables Using the Set Command - batch-file

I'm required to write a program that displays the computer name, username, and path to user files. All of these should be taken from local system variables. It's been hinted that I'm supposed to use the set command, however, I'm not sure how to use the set command in this situation... I had assumed that I could just use echo %COMPUTERNAME% etc. How can I implement the set command?

I'm guessing that the hint about the Set command was so that you could use the output of it to help you identify the local system variables to use in your batch file, not that you need to use Set to output them.
When you enter Set at the Command prompt you'll get output showing you each of the defined system variables.
Additionally, if you enter Set ComputerName at the prompt, you should get output showing you all variables which begin with the string ComputerName.
So based on the output of the Set command you could Echo, your three variables from a batch file like this:
#Echo Off
Echo %ComputerName%
Echo %UserName%
Echo %UserProfile%
You could also include the variables with their values:
#Echo Off
Echo %%ComputerName%%=%ComputerName%
Echo %%UserName%%=%UserName%
Echo %%UserProfile%%=%UserProfile%
You could also consider running a simple For loop in your batch file to show the same content using the Set command directly:
#Echo Off
For %%A In (ComputerName,UserName,UserProfile) Do Set %%A
Pause
Or you could return just their values using Set and Echo from nested For loops:
#Echo Off
For %%A In (ComputerName,UserName,UserProfile) Do (
For /F "Tokens=1* Delims==" %%B In ('Set %%A') Do Echo %%C)
Pause

to take the question very literal ("display the computer name ... using set command"):
set computername
set username
set userprofile
output like:
COMPUTERNAME=Elon-PC
USERNAME=Muscrat
USERPROFILE=C:\Users\Muskrat
(Compo already has this method in his answer, but I guess using the for command is over the boundaries of the current state of your course)
(Note: for practical use, in most cases Compo's answer (using variables) is better, because in practice, you will probably do something with the values, not "just" show them, but this literally answers your question)

Related

Using CMDER, issue with setting PATH

I'm trying to use CMDER for a development environment that I've setup.
Basically I've created a .bat file that calls:
#ECHO OFF
start Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\Cmder.exe
Then I've placed the file startdev.bat in:
%CMDER_HOME%\config\profile.d
So everything seems to work just fine, but when the startdev.bat finishes, issuing an:
echo %PATH%
returns:
Z:\_DEV\OS_WINDOWS\1_COMPILER\JDK\ORACLE\1.8.0_181\bin;Z:\_DEV\OS_CYGWIN\bin;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CLutils;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\PUTTY;Z:\_DEV\OS_WINDOWS\6_VERSION_CONTROL\PortableGit\bin;C:\WINDOWS;C:\WINDOWS\SysWOW64;C:\WINDOWS\System32
...any idea what's happening?
I would either expect CMDER to override PATH with the value from its own settings, or use my full path, which before the startdev.bat ends shows the value of:
PATH=Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\vendor\conemu-maximus5;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\vendor\conemu-maximus5\ConEmu;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CMDER\vendor\conemu-maximus5\ConEmu\Scripts;Z:\_DEV\OS_ALL\JVM\3_BUILD_TOOLS\GRADLE\5.4\bin;Z:\_DEV\OS_ALL\JVM\3_BUILD_TOOLS\MAVEN\3.5.4\bin;Z:\_DEV\OS_ALL\JVM\3_BUILD_TOOLS\ANT\1.10.5\bin;Z:\_DEV\OS_WINDOWS\3_BUILD_TOOLS\NODE\LTS\10.15.3;Z:\_DEV\OS_WINDOWS\3_BUILD_TOOLS\NODE\LTS\10.15.3\node_modules;Z:\_DEV\OS_WINDOWS\1_COMPILER\GO\1.12.4\bin;Z:\_DEV\OS_WINDOWS\1_COMPILER\PYTHON\32bit\2.7.13;Z:\_DEV\OS_WINDOWS\1_COMPILER\PYTHON\32bit\2.7.13\scripts;Z:\_DEV\OS_WINDOWS\1_COMPILER\ANDROID\android-sdk-windows\platform-tools;Z:\_DEV\OS_WINDOWS\1_COMPILER\JDK\ORACLE\1.8.0_181\bin;Z:\_DEV\OS_CYGWIN\bin;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\CLutils;Z:\_DEV\OS_WINDOWS\9_MISC_TOOLS\PUTTY;Z:\_DEV\OS_WINDOWS\6_VERSION_CONTROL\PortableGit\bin;C:\WINDOWS;C:\WINDOWS\SysWOW64;C:\WINDOWS\System32
..but the fact that it only seems to be keeping the value as defined about halfway through the batch job is strange.
Any ideas?
First I recommend opening a command prompt window and run setlocal /? and endlocal /? to get displayed the help/documentation for those two commands. Very important to know is that every setlocal without a corresponding endlocal results in an implicit execution of endlocal by cmd.exe before exiting processing of a batch file or a subroutine called with command CALL.
Next I suggest reading this answer for even more details about the commands SETLOCAL and ENDLOCAL and what happens on using them.
I suggest like michael_heath to change this code block:
setLocal EnableDelayedExpansion
set CLASSPATH=.
for /R %JRE_HOME%\lib %%a in (*.jar) do (
set CLASSPATH=!CLASSPATH!;%%a
)
set CLASSPATH=!CLASSPATH!
Better would be:
setLocal EnableExtensions EnableDelayedExpansion
set CLASSPATH=.
for /R "%JRE_HOME%\lib" %%a in (*.jar) do set "CLASSPATH=!CLASSPATH!;%%a"
endlocal & set "CLASSPATH=%CLASSPATH%"
Now the local environment is ended with passing the environment variable CLASSPATH from local environment, on which it was defined, to the restored previous environment because of cmd.exe expands %CLASSPATH% to current value of the environment variable CLASSPATH in current local environment before executing the command endlocal which restores the previous environment.
Wrong in your batch file is also set WINDIR=%SystemRoot%;%SystemRoot% which should be set "WINDIR=%SystemRoot%".
I recommend further reading Why is no string output with 'echo %var%' after using 'set var = text' on command line? It explains why the syntax set "variable=string value" is recommended nowadays. Many of the environment variable definitions use directly or indirectly %UserProfile% which means depending on whatever the user currently running the batch file has entered as user name on creation of the user account. I have seen users entering their name containing a space and non ASCII characters. And I have seen users creating an account with a user name containing character & like Company GmbH & Co. An ampersand outside a double quoted argument string is interpreted as AND operator and cmd.exe tries to execute after set also the remaining string after & as command line on using something like set USERHOME=%DEVHOME%\%USERNAME% instead of set "USERHOME=%DEVHOME%\%USERNAME%". Well, startdev.bat redefines nearly all predefined Windows Environment Variables including USERNAME and USERPROFILE and so is written safe for most environment variable definitions.
This code block is also not optimal:
FOR /F "usebackq" %%i IN (`hostname`) DO SET HOSTNAME=%%i
echo Running on hostname: %HOSTNAME%
The host name respectively computer name could contain also a space or characters critical for command line or start with a semicolon for some unknown reason. So better would be:
FOR /F delims^=^ eol^= %%i IN ('hostname') DO SET "HOSTNAME=%%i"
setlocal EnableDelayedExpansion & echo Running on host name: !HOSTNAME!& endlocal
Whereby there is the environment variable COMPUTERNAME predefined by Windows making it possible to use just following command line:
setlocal EnableDelayedExpansion & echo Running on host name: !ComputerName!& endlocal
An ECHO command line containing an immediately expanded environment variable reference on which it is unknown if its value contains &|<> is always a problem because of the environment variable reference is expanded before further processing of the command line by cmd.exe as described at How does the Windows Command Interpreter (CMD.EXE) parse scripts?
I suggest also reading DosTips forum topic ECHO. FAILS to give text or blank line - Instead use ECHO/ and avoid the usage of echo. in the batch file to output an empty line.
"halfway through the batch job" as you have a
setLocal EnableDelayedExpansion which sets any further
changes to the variable PATH or other set variables as local.
The endLocal not specified is implied at the end of the script.
To resolve this, use endLocal and set CLASSPATH=%CLASSPATH%
on the same parsed line to set CLASSPATH as global.
Change this part:
setLocal EnableDelayedExpansion
set CLASSPATH=.
for /R %JRE_HOME%\lib %%a in (*.jar) do (
set CLASSPATH=!CLASSPATH!;%%a
)
set CLASSPATH=!CLASSPATH!
to this:
setLocal EnableDelayedExpansion
set CLASSPATH=.
for /R %JRE_HOME%\lib %%a in (*.jar) do (
set CLASSPATH=!CLASSPATH!;%%a
)
endLocal & set CLASSPATH=%CLASSPATH%
After that changed part, the script will set variables as global again.

set /p not taking environment variables

I am trying to match a batch script to do this tutorial automatically, for any system.
#echo off
for /f "tokens=4* delims= " %%A in ('reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Pictures"') do (set loc=%%A %%B)
set loc=%loc%\Spotlight
set /p loc=Location for images (default - "%loc%") [use %%loc%% for default]?:
start robocopy "%localappdata%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets" "%temp%\spotlight"
ren %temp%\spotlight\*.* *.jpg
robocopy "%temp%\spotlight" "%loc%"
start %SystemRoot%\explorer.exe %loc%
However, if I try typing %loc%\Spotlight2, it places it in the Desktop\%loc%\spotlight2 (desktop is the current working directory).
Is there a way to make set /p take environment variables?
the usual way to enter a default is an empty input (keeps predefined varable unchanged). But there is a way to enable a variable input. Try the following and answer the question with %windir%
#echo off
setlocal
set x=%username%
set /p "x=enter value ([ENTER] for default: "%x%") "
call set x=%x%
echo %x%
The trick is to expand the variable twice by using another layer of parsing (whith call).
SET /P is basically just an input routine. There is no documented way to have it do further evaluation, and I doubt one exists.
One could try to get CMD to evaluate the contents of a variable to expand any variables in the contents -- I have seem kludges to do this. However, I don't think that is a good way to do what you want.
I think you would be better off using something easier to type, and testing for that explicitly. For example:
set loc=%loc%\Spotlight
echo Enter location for images, or just press [ENTER] to use the default.
echo Default location: %loc%
set userloc=*
set /p userloc=Location?
if not "%userloc%"=="*" set loc=%userloc%
There's a way to do what you want without default locations! It involves variable manipulation:
...
setlocal enabledelayedexpansion
set loc=%loc%\Spotlight
set default=%loc%
set /p "loc=Location [%loc%] for default: "
set out=!loc:%%loc%%=%default%!
echo %out%
...
Hence, typing %loc% replaces it with the original value of loc.
I tested this by typing %loc%\s and it performed as expected. In terms of it being the correct directory, thats to do with how you set the value of loc prior to this code.

set /p is not working as expected

I am trying to create the interactive bat file which ask for the folder details it is able to take the userchoice but after that it is not able to set the folder path given by useri.e. it takes the path till Desktop only.Below is my code for the same:
#echo off
set /p UserInfo= "Do you have abc software(y/n)? "
echo %UserInfo% // here it is working as expected
IF %UserInfo%==y (
echo "Reply is true-----"
set /p Path= "Please enter path for abc directory? "
echo %Path% //but here it takes the path till the desktop only(C:\user\username\Desktop)
CD %Path%
dir
set /p Path1= "Please enter path1 directory path provided in package? "
echo %Path1% //but here it takes the path till the desktop only(C:\user\username\Desktop)
CD %Path1%
)
IF %UserInfo%==n (
echo "Reply is False**************"
)
pause
How to read the folder directive?
Hmm.. Please use the search bar as user Magoo, LotPings said.
Also, Stephan & Squashman mentioned, do not set a variable with the name path because there is a internal variable named path. If you rename it, other programs may not work properly.
What's DelayedExpansion?
When batch files are run, cmd process them line by line. The entire if statement get processed at once. That's why the variable are un-set.
Since we want cmd to process those variable at run-time, we will need to tell it to do so, by adding setlocal enableDelayedExpansion. This enables run-time variable expansion. To disable, just change enable to disable.
You may want to add it like so:
#echo off
setlocal enableDelayedExpansion
rem your code follows...
How To Make Variable Get Processed Run-Time?
Simply change %var% to !var!.
Please note that for loop metavariable %%n cannot be changed to !!n, since itself already implicated a delayed expansion.
Command-line arguments %n cannot be changed to !n. You may want to do this instead:
if "%var%"=="abc" (
set variable=%1
echo !variable!
)
SET /P Code Injection Cause Security Issue?!
If the input of %Userinput% is a==a format D:\ && echo, cmd sees:
if a==a
do format D:\
do echo ==y (
Which... formats your D drive. Adding quotes like if "%var%"=="abc" won't help since user can just escape the quote and execute the commands.
See here for more info.
SET /P Alternatives
You may want to consider CHOICE for single letter choice. It's command syntax is like so:
choice /c choices /n /cs /t timeout /d default_choice /m prompt
/n hides the list of options, letting /m to display it's own prompt
/cs == case-insensitive.
PATH Variable
Again mentioned above, PATH is a internal variable used by Windows and other programs. Mis-setting it may cause some Windows functions or programs to stop functioning properly.
Instead, use another variable name like programPath.

Batch file include external file for variables

I have a batch file and I want to include an external file containing some variables (say configuration variables). Is it possible?
Note: I'm assuming Windows batch files as most people seem to be unaware that there are significant differences and just blindly call everything with grey text on black background DOS. Nevertheless, the first variant should work in DOS as well.
Executable configuration
The easiest way to do this is to just put the variables in a batch file themselves, each with its own set statement:
set var1=value1
set var2=value2
...
and in your main batch:
call config.cmd
Of course, that also enables variables to be created conditionally or depending on aspects of the system, so it's pretty versatile. However, arbitrary code can run there and if there is a syntax error, then your main batch will exit too. In the UNIX world this seems to be fairly common, especially for shells. And if you think about it, autoexec.bat is nothing else.
Key/value pairs
Another way would be some kind of var=value pairs in the configuration file:
var1=value1
var2=value2
...
You can then use the following snippet to load them:
for /f "delims=" %%x in (config.txt) do (set "%%x")
This utilizes a similar trick as before, namely just using set on each line. The quotes are there to escape things like <, >, &, |. However, they will themselves break when quotes are used in the input. Also you always need to be careful when further processing data in variables stored with such characters.
Generally, automatically escaping arbitrary input to cause no headaches or problems in batch files seems pretty impossible to me. At least I didn't find a way to do so yet. Of course, with the first solution you're pushing that responsibility to the one writing the config file.
If the external configuration file is also valid batch file, you can just use:
call externalconfig.bat
inside your script. Try creating following a.bat:
#echo off
call b.bat
echo %MYVAR%
and b.bat:
set MYVAR=test
Running a.bat should generate output:
test
Batch uses the less than and greater than brackets as input and output pipes.
>file.ext
Using only one output bracket like above will overwrite all the information in that file.
>>file.ext
Using the double right bracket will add the next line to the file.
(
echo
echo
)<file.ext
This will execute the parameters based on the lines of the file. In this case, we are using two lines that will be typed using "echo". The left bracket touching the right parenthesis bracket means that the information from that file will be piped into those lines.
I have compiled an example-only read/write file. Below is the file broken down into sections to explain what each part does.
#echo off
echo TEST R/W
set SRU=0
SRU can be anything in this example. We're actually setting it to prevent a crash if you press Enter too fast.
set /p SRU=Skip Save? (y):
if %SRU%==y goto read
set input=1
set input2=2
set /p input=INPUT:
set /p input2=INPUT2:
Now, we need to write the variables to a file.
(echo %input%)> settings.cdb
(echo %input2%)>> settings.cdb
pause
I use .cdb as a short form for "Command Database". You can use any extension.
The next section is to test the code from scratch. We don't want to use the set variables that were run at the beginning of the file, we actually want them to load FROM the settings.cdb we just wrote.
:read
(
set /p input=
set /p input2=
)<settings.cdb
So, we just piped the first two lines of information that you wrote at the beginning of the file (which you have the option to skip setting the lines to check to make sure it's working) to set the variables of input and input2.
echo %input%
echo %input2%
pause
if %input%==1 goto newecho
pause
exit
:newecho
echo If you can see this, good job!
pause
exit
This displays the information that was set while settings.cdb was piped into the parenthesis. As an extra good-job motivator, pressing enter and setting the default values which we set earlier as "1" will return a good job message.
Using the bracket pipes goes both ways, and is much easier than setting the "FOR" stuff. :)
So you just have to do this right?:
#echo off
echo text shizzle
echo.
echo pause^>nul (press enter)
pause>nul
REM writing to file
(
echo XD
echo LOL
)>settings.cdb
cls
REM setting the variables out of the file
(
set /p input=
set /p input2=
)<settings.cdb
cls
REM echo'ing the variables
echo variables:
echo %input%
echo %input2%
pause>nul
if %input%==XD goto newecho
DEL settings.cdb
exit
:newecho
cls
echo If you can see this, good job!
DEL settings.cdb
pause>nul
exit
:: savevars.bat
:: Use $ to prefix any important variable to save it for future runs.
#ECHO OFF
SETLOCAL
REM Load variables
IF EXIST config.txt FOR /F "delims=" %%A IN (config.txt) DO SET "%%A"
REM Change variables
IF NOT DEFINED $RunCount (
SET $RunCount=1
) ELSE SET /A $RunCount+=1
REM Display variables
SET $
REM Save variables
SET $>config.txt
ENDLOCAL
PAUSE
EXIT /B
Output:
$RunCount=1
$RunCount=2
$RunCount=3
The technique outlined above can also be used to share variables among multiple batch files.
Source: http://www.incodesystems.com/products/batchfi1.htm
Kinda old subject but I had same question a few days ago and I came up with another idea (maybe someone will still find it usefull)
For example you can make a config.bat with different subjects (family, size, color, animals) and apply them individually in any order anywhere you want in your batch scripts:
#echo off
rem Empty the variable to be ready for label config_all
set config_all_selected=
rem Go to the label with the parameter you selected
goto :config_%1
REM This next line is just to go to end of file
REM in case that the parameter %1 is not set
goto :end
REM next label is to jump here and get all variables to be set
:config_all
set config_all_selected=1
:config_family
set mother=Mary
set father=John
set sister=Anna
rem This next line is to skip going to end if config_all label was selected as parameter
if not "%config_all_selected%"=="1" goto :end
:config_test
set "test_parameter_all=2nd set: The 'all' parameter WAS used before this echo"
if not "%config_all_selected%"=="1" goto :end
:config_size
set width=20
set height=40
if not "%config_all_selected%"=="1" goto :end
:config_color
set first_color=blue
set second_color=green
if not "%config_all_selected%"=="1" goto :end
:config_animals
set dog=Max
set cat=Miau
if not "%config_all_selected%"=="1" goto :end
:end
After that, you can use it anywhere by calling fully with 'call config.bat all' or calling only parts of it (see example bellow)
The idea in here is that sometimes is more handy when you have the option not to call everything at once. Some variables maybe you don't want to be called yet so you can call them later.
Example test.bat
#echo off
rem This is added just to test the all parameter
set "test_parameter_all=1st set: The 'all' parameter was NOT used before this echo"
call config.bat size
echo My birthday present had a width of %width% and a height of %height%
call config.bat family
call config.bat animals
echo Yesterday %father% and %mother% surprised %sister% with a cat named %cat%
echo Her brother wanted the dog %dog%
rem This shows you if the 'all' parameter was or not used (just for testing)
echo %test_parameter_all%
call config.bat color
echo His lucky color is %first_color% even if %second_color% is also nice.
echo.
pause
Hope it helps the way others help me in here with their answers.
A short version of the above:
config.bat
#echo off
set config_all_selected=
goto :config_%1
goto :end
:config_all
set config_all_selected=1
:config_family
set mother=Mary
set father=John
set daughter=Anna
if not "%config_all_selected%"=="1" goto :end
:config_size
set width=20
set height=40
if not "%config_all_selected%"=="1" goto :end
:end
test.bat
#echo off
call config.bat size
echo My birthday present had a width of %width% and a height of %height%
call config.bat family
echo %father% and %mother% have a daughter named %daughter%
echo.
pause
Good day.
The best option according to me is to have key/value pairs file as it could be read from other scripting languages.
Other thing is I would prefer to have an option for comments in the values file - which can be easy achieved with eol option in for /f command.
Here's the example
values file:
;;;;;; file with example values ;;;;;;;;
;; Will be processed by a .bat file
;; ';' can be used for commenting a line
First_Value=value001
;;Do not let spaces arround the equal sign
;; As this makes the processing much easier
;; and reliable
Second_Value=%First_Value%_test
;;as call set will be used in reading script
;; refering another variables will be possible.
Third_Value=Something
;;; end
Reading script:
#echo off
:::::::::::::::::::::::::::::
set "VALUES_FILE=E:\scripts\example.values"
:::::::::::::::::::::::::::::
FOR /F "usebackq eol=; tokens=* delims=" %%# in (
"%VALUES_FILE%"
) do (
call set "%%#"
)
echo %First_Value% -- %Second_Value% -- %Third_Value%
While trying to use the method with excutable configuration
I noticed that it may work or may NOT work
depending on where in the script is located the call:
call config.cmd
I know it doesn't make any sens, but for me it's a fact.
When "call config.cmd" is located at the top of the
script, it works, but if further in the script it doesn't.
By doesn't work, I mean the variable are not set un the calling script.
Very very strange !!!!

Windows Batch help in setting a variable from command output [duplicate]

This question already has answers here:
Set output of a command as a variable (with pipes) [duplicate]
(6 answers)
Closed 7 years ago.
I need to run a simple find command and redirect the output to a variable in a Windows Batch File.
I have tried this:
set file=ls|find ".txt"
echo %file%
But it does not work.
If I run this command it works without problems:
set file=test.txt
echo %file%
So obviously my command output is not being set to my variable. Can anyone help? Thanks
I just find out how to use commands with pipes in it, here's my command (that extracts the head revision of an svn repo) :
SET SVN_INFO_CMD=svn info http://mySvnRepo/MyProjects
FOR /f "tokens=1 delims=" %%i IN ('%SVN_INFO_CMD% ^| find "Revision"') DO echo %%i
First of all, what you seem to expect from your question isn't even possible in UNIX shells. How should the shell know that ls|find foo is a command and test.txt is not? What to execute here? That's why UNIX shells have the backtick for such things. Anyway, I digress.
You can't set environment variables to multi-line strings from the shell. So we now have a problem because the output of ls wouldn't quite fit.
What you really want here, though, is a list of all text files, right? Depending on what you need it's very easy to do. The main part in all of these examples is the for loop, iterating over a set of files.
If you just need to do an action for every text file:
for %%i in (*.txt) do echo Doing something with "%%i"
This even works for file names with spaces and it won't erroneously catch files that just have a .txt in the middle of their name, such as foo.txt.bar. Just to point out that your approach isn't as pretty as you'd like it to be.
Anyway, if you want a list of files you can use a little trick to create arrays, or something like that:
setlocal enabledelayedexpansion
set N=0
for %%i in (*.txt) do (
set Files[!N!]=%%i
set /a N+=1
)
After this you will have a number of environment variables, named Files[0], Files[1], etc. each one containing a single file name. You can loop over that with
for /l %%x in (1,1,%N%) do echo.!Files[%%x]!
(Note that we output a superfluous new line here, we could remove that but takes one more line of code :-))
Then you can build a really long line of file names, if you wish. You might recognize the pattern:
setlocal enabledelayedexpansion
set Files=
for %%i in (*.txt) do set Files=!Files! "%%i"
Now we have a really long line with file names. Use it for whatever you wish. This is sometimes handy for passing a bunch of files to another program.
Keep in mind though, that the maximum line length for batch files is around 8190 characters. So that puts a limit on the number of things you can have in a single line. And yes, enumerating a whole bunch of files in a single line might overflow here.
Back to the original point, that batch files have no way of capturing a command output. Others have noted it before. You can use for /f for this purpose:
for /f %%i in ('dir /b') do ...
This will iterate over the lines returned by the command, tokenizing them along the way. Not quite as handy maybe as backticks but close enough and sufficient for most puposes.
By default the tokens are broken up at whitespace, so if you got a file name "Foo bar" then suddenly you would have only "Foo" in %%i and "bar" in %%j. It can be confusing and such things are the main reason why you don't ever want to use for /f just to get a file listing.
You can also use backticks instead of apostrophes if that clashes with some program arguments:
for /f "usebackq" %%i in (`echo I can write 'apostrophes'`) do ...
Note that this also tokenizes. There are some more options you can give. They are detailed in the help for command.
set command has /p option that tells it to read a value from standard input. Unfortunately, it does not support piping into it, but it supports reading a value from a first line of existing file.
So, to set your variable to the name of a first *.txt file, you could do the following:
dir /b *.txt > filename.tmp
set /p file=< filename.tmp
del /q filename.tmp
It is important not to add a space before or even after =.
P. S. No fors, no tokens.
Here's a batch file which will return the last item output by find:
#echo off
ls | find ".txt" > %temp%\temp.txt
for /f %%i in (%temp%\temp.txt) do set file=%%i
del %temp%\temp.txt
echo %file%
for has a syntax for parsing command output, for /f "usebackq", but it cannot handle pipes in the command, so I've redirected output to a temporary location.
I strongly recommend, given that you have access to ls, that you consider using a better batch language, such as bash or even an scripting language like python or ruby. Even bash would be a 20x improvement over cmd scripting.
The short answer is: Don't!
A windows shell env var can hold a max of 32 Kb and it isn't safe to save output from programs in them.
That's why you can't. In batch script you must adopt another programming style. If you need all of the output
from the program then save it to file. If you only need to check for certain properties then pipe the output into
a program that does the checking and use the errorlevel mechanism:
#echo off
type somefile.txt | find "somestring" >nul
if %errorlevel% EQU 1 echo Sorry, not found!
REM Alternatively:
if errorlevel 1 echo Sorry, not found!
However, it's more elegant to use the logical operators Perl style:
#echo off
(type somefile.txt | find "somestring" >nul) || echo Sorry, not found!
It's not available in DOS, but in the Windows console, there is the for command. Just type 'help for' at a command prompt to see all of the options. To set a single variable you can use this:
for /f %%i in ('find .txt') do set file=%%i
Note this will only work for the first line returned from 'find .txt' because windows only expands variable once by default. You'll have to enable delayed expansion as shown here.
what you are essentially doing is listing out .txt files. With that, you can use a for loop to over dir cmd
eg
for /f "tokens=*" %%i in ('dir /b *.txt') do set file=%%i
or if you prefer using your ls, there's no need to pipe to find.
for /f "tokens=*" %%i in ('ls *.txt') do set file=%%i
Example of setting a variable from command output:
FOR /F "usebackq" %%Z IN ( `C:\cygwin\bin\cygpath "C:\scripts\sample.sh"` ) DO SET BASH_SCRIPT=%%Z
c:\cygwin\bin\bash -c '. ~/.bashrc ; %BASH_SCRIPT%'
Also, note that if you want to test out the FOR command in a DOS shell, then you need only use %Z instead of %%Z, otherwise it will complain with the following error:
%%Z was unexpected at this time.

Resources