Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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

like image 363
Steve Avatar asked Nov 17 '09 03:11

Steve


People also ask

How do you repeat a command in CMD?

F3: Repeat the previous command. Up/Down Arrow: Scroll backward and forwards through previous commands you've typed in the current session.

What is == in batch?

[ == ] (Double Equals) The "IF" command uses this to test if two strings are equal: IF "%1" == "" GOTO HELP. means that if the first parameter on the command line after the batch file name is equal to nothing, that is, if a first parameter is not given, the batch file is to go to the HELP label.

How do I echo a variable in CMD?

To reference a variable in Windows, use %varname% (with prefix and suffix of '%' ). For example, you can use the echo command to print the value of a variable in the form " echo %varname% ".


2 Answers

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 
like image 180
Grokwik Avatar answered Sep 30 '22 16:09

Grokwik


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.

like image 21
Joey Avatar answered Sep 30 '22 18:09

Joey