Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible in a batch file to read from a pipe line by line?

Tags:

batch-file

cmd

I was wondering if it is possible to read from a pipe in a batch file. If I write:

echo Test

i get, unsurprising, Test. That's nice. But what if I want to pipe the output, and read it from another command?

echo Test | echo ???

How to obtain the same result as before, but through a pipe? Thanks!

EDIT: what I am after really after is this.

I have a list of files, and i need to filter this list with some words that i put, line by line, in a file named filter.txt. So I have to use findstr /g:filter.txt.

But then I need to do something to the list files that matches, and since findstr returns one row for each file, i have to read the matches line by line.

This is how i did it:

dir /b | findstr /g:filter.txt | for /F "delims=" %a in ('more') do del "%a"

SOLUTION:

It looks like that what I wanted to do was not reading from a pipe but just reading the output of another command in a batch file.

To do a single line read, you could use this:

echo Test | ( set /p line= & call echo %%line%%)

or you can use this, that works also with multi line input:

echo Test | for /F "delims=" %a in ('more') do @echo %a

(this trick of using more could be useful in some situations). But in my particular case, the solution is this:

for /F "delims=" %a in ('echo Test') do @echo %a

Thanks to everyone!

like image 519
fthiella Avatar asked Nov 13 '12 22:11

fthiella


People also ask

How do I read a text file line by line in a batch file?

Reading of files in a Batch Script is done via using the FOR loop command to go through each line which is defined in the file that needs to be read. Since there is a no direct command to read text from a file into a variable, the 'for' loop needs to be used to serve this purpose.

What does pipe do in batch?

The pipe operator (|) takes the output (by default, STDOUT) of one command and directs it into the input (by default, STDIN) of another command.

Does pipe work in CMD?

Pipe shell command The | command is called a pipe. It is used to pipe, or transfer, the standard output from the command on its left into the standard input of the command on its right. # First, echo "Hello World" will send Hello World to the standard output.


2 Answers

Based on this answer https://stackoverflow.com/a/6980605/1630171 it looks like that a way to answer my question is this:

echo Test | for /F "delims=" %a in ('more') do @echo %a

It's a bit weird but it works :)

It only looks a little strange to me that there's no native solution to this... but this does exactly what i want!

like image 116
fthiella Avatar answered Oct 14 '22 06:10

fthiella


Excuse me, I think there is a confusion here...

You said you want to read from a pipe. A pipe is used to redirect the output of one command into the input of another command; the second command is called filter. For example, in

dir /b | findstr /g:filter.txt

there is a pipe between dir and findstr commands. A pipe is always established between two processes. There is no way to read the data that flow from dir command to findstr command (that is the only pipe that exist here). However, you can read from the output of findstr command.

If we insert an additional filter, the behavior is the same. For example, in

dir /b | findstr /g:filter.txt | more

there are two pipes, but there is no way to read from anyone of them. However, you can read from the output of the last command (more in this case). What is the native Batch solution to read the output of one command? It is the FOR /F command. For example, the native way to get echo command output in:

echo Test | for /F "delims=" %a in ('more') do @echo %a

is:

for /F "delims=" %a in ('echo Test') do @echo %a

Please note that in the first example the %a parameter does NOT get the information from the pipe that exist between echo and for commands, but from the output of more command.

In the same way, the natural method to achieve this task:

dir /b | findstr /g:filter.txt | for /F "delims=" %a in ('more') do del "%a"

is this way:

for /F "delims=" %a in ('dir /b ^| findstr /g:filter.txt') do del "%a"

that process the multi-line output of findstr command.

Second method is not just faster than the former, but it is also clearer because the inclusion of a more command that really do nothing may lead to undesired misconceptions or errors.

Antonio

like image 45
Aacini Avatar answered Oct 14 '22 06:10

Aacini