Reputation: 537
I try to understand how output redirection to another command works.
I know that it can be used if the second command is find as help text to find explicitly says so. It can also be used with findstr although findstr's help text does not say anything about this.
So the question is:
How do I know what other windows command shell commands accept output from another command?
I've created a command line where I expect the output to be "18:33" but it does not work
C:>time /T | set /P a= && echo %a%
%a%
C:>setlocal enabledelayedexpansion
C:>time /T | set /P a= && echo !a!
!a!
Why does this not work as expected?
Please not that the point here is not reading the time to a variable. I just don't see how the pipe is useful with anything other than find or findstr.
Upvotes: 3
Views: 2913
Reputation: 49097
Commands reading in data from a file often but not always support also reading in data from handle STDIN. The pipe character |
redirects the output written to handle STDOUT of application A to handle STDIN of application B. For more details read the Microsoft article about Using command redirection operators and SS64 article about Redirection.
Which console applications support input from STDIN is a matter of documentation. There are just a few console applications installed with Windows supporting input from STDIN. But there are lots of third-party console applications supporting input from STDIN. Many of them don't explicitly explain in documentation that input can be read also from STDIN and not only from an input file specified as parameter. But support of data input from STDIN can be always found out very quickly with one trial.
Standard Windows console applications supporting also STDIN among FIND and FINDSTR are for example MORE and SORT.
Most standard Windows console applications and internal commands of cmd.exe
do not process the contents of files and therefore don't support STDIN. For a list of Windows standard commands see Microsoft's command-line reference. But more details about the Windows standard command line commands can be found on the webpages linked from SS64.com - A-Z index of the Windows CMD command line.
Redirection from STDOUT of an application to STDIN of another application is very often used with third-party console applications because many of them support input from STDIN. Every compiler/script interpreter writes messages to STDOUT and fatal error messages to STDERR which are redirected by many GUI text editors and IDE applications for capturing, filtering and printing those messages into a GUI window for the programmer. This redirection is done using same mechanisms as Windows command interpreter offers with the redirection operators >
and >>
and |
.
In general all console applications supporting input from keyboard support also input from STDIN redirected from output or another application or from a file. But as always there are exceptions as for example some applications by design accept input only directly from keyboard and not from handle STDIN for example because of security reasons like not an application or script should confirm/enter something, but a real human user via keyboard.
The command SET is for assigning a value to an environment variable, or outputting the values of 1 or more environment variables to STDOUT, or evaluating an arithmetic expression, or prompting a batch user for a string reading from STDIN. This command is not designed for reading from a file or writing to a file.
But it is nevertheless possible to redirect output of an application to an environment variable using set /P
and a special syntax as jeb describes in his answer. But this method is rarely used and I think the reason is the complexity of the required expression.
However, the demo code is for assigning the current time to an environment variable. Very often there is a command parameter or another feature which avoids the need to redirect text to STDIN of a command or console application. This is also the case for getting an environment variable with current time as value.
There are the predefined environment variables DATE and TIME. Run in a command prompt window set /?
and read all pages of output help. On last page some special environment variables often needed in batch file are listed with an explanation including DATE and TIME.
Try it out with
echo Current date is %DATE% and current time is %TIME%
Please note that format of date and time string returned by %DATE%
and %TIME%
depends on current settings in Windows Region and Language settings (country). So use %DATE%
and %TIME%
only if the batch file is executed always on same computer where date/time format is well known and does not change. Otherwise it is better to use wmic.exe OS get localdatetime
. For more details about date/time usage on Windows see answer on Find out if file is older than 4 hours in Batch file.
The command FOR can be used to assign a string output by an application to 1 or more environment variables. Run in a command prompt window for /?
for a help on this command. The method with usage of FOR is most often used to assign output of an application or a text read from a file to an environment variable.
Batch file example:
@echo off
for /F %%I in ('time /T') do set "a=%%I"
echo Time is %a%
Upvotes: 1
Reputation: 82307
Nearly every command that accepts input can also be used with pipes.
Also your sample with SET /P
could work, but it needs some attention.
I don't use delayed expasion here, as it adds only more complexity.
time /T | ( set /P var= && set var )
The parenthesis are important here, else the implicit order would be
( time /T | set /P var= ) && set var
But this fails, as a pipe creates two new cmd.exe instances for both sides.
After the end of the both tasks these instances will be removed again.
Therefore it's only possible to access a variable created by a pipe inside the same (new) instance.
For many cases, pipes are useful to automate some simple questions like
echo Y | del *
Some more infos about pipes and delayed expansion at SO:Why does delayed expansion fail when inside a piped block of code?
Upvotes: 3
Reputation: 61995
The short answer is because windows is messed up.
There is no good reason why your commands above do not work, and microsoft is entirely to blame. Their software quite often not only fails to work, but it actually fails to work in completely nonsensical ways, and without any error message to hint at what might have gone wrong, thus wasting people's time. If you want a decent command prompt which usually works, and in the event that it does not work it is generally due to your mistake and not its mistake, try Linux.
That having been said, there are several commands available at the windows command prompt that do process their standard input; the sort
command is one that comes to mind. Try type text.txt | sort
and see what happens.
To answer your question "how do I know?", the answer is that you cannot know, because I do not think that there is a comprehensive list of all commands that process the standard input. However, generally, if a command operates on an input file, and it requires the input file name to be specified as a parameter, and if this parameter is optional, then it is pretty safe to assume that if the parameter is omitted, the command will process its standard input.
Also, it is possible to fool a command which accepts the input file name as a non-optional parameter to use the standard input instead, by specifying con
as the input file name. So, for example, typing type
alone does not work, but try type con
and see what happens.
Upvotes: 1