I've been learning batch scripting so I came across pipes and I/O redirection.
If this works:
tasklist | find "winword"
Why does this not:
cd | explorer
I expect this command to open explorer at current working directory as cd without any parameters outputs current directory and:
explorer %directory%
opens explorer at %directory%.
Is there something I am doing wrong here?
Open a Command Prompt window, type find "blah" and press Enter; you'll see it awaits user/keyboard/console input, which STDIN points to (press Ctrl+Z and Enter to end the prompt). Then type echo blah and press Enter; you'll notice the text blah is printed, so there is display/console output; this is pointed to by STDOUT. A pipe | takes the data at STDOUT from the left-side command and redirects it into STDIN for the right-side command.
Now type explorer into the Command Prompt window; of course an Explorer Window pops up, but what happens in the Command Prompt? right, nothing, it does not await any input at STDIN. So you can pipe to it but it will not care as it does not read at STDIN. In fact, GUI applications do generally not use STDIN and STDOUT, because these things are intended for command line applications.
Yet another example: in a Command Prompt window, type echo C:\Windows; quite obvious what will happen; then type echo C:\Windows| dir; what happens? dir returns the contents of the current directory but not of C:\Windows. Why? well, let's type dir first and see what happens: yes, dir shows the contents of the current directory, and it does not await console input; so at the right side of the pipe it receives data at STDIN but it simply doesn't care. You can try using dir "C:\some\other\folder", without and with the pipe, the output is just the same, STDIN is ignored here.
The echo/dir example also demonstrates the difference between console input (STDIN) and command line arguments or parameters: the path in the command line dir "C:\some\other\folder" is such an argument, and you cannot replace it by data from STDIN. To understand why, you need to distinguish between parse time (when the command is read and parsed by the interpreter) and run time (when the command is actually executed): arguments already have to be present at parse time, whilst STDIN is only relevant during run time, which is later. So we can say they just never meet.
This also reflects the situation with your attempt cd | explorer: the latter accepts command line arguments (which anyway need to be available before execution, so at parse time), but it doesn't care about STDIN. Also the STDOUT data from cd isn't available before execution (but only during run time), so it would arrive too late anyway...
Related
I know that one can close stdin when executing a command from a Linux CLI using logic such as:
0<&- <command>
This simulates/emulates running an application unattended, or within a CI/CD system such as Jenkins/Gitlab that has stdin closed.
Why do I care? Because we have an application that has a "Press any key to continue..." prompt.
When run under Jenkins/Gitlab or anything that doesn't have stdin open, it just moves on..... when run on Linux.
How would I do this, and is this possible to do this from the Windows CMD Window CLI?
I've tried 0<&- and that results in the message
0<& was unexpected at this time.
Google search gives many hits for stdin but all the documentation is on redirection. I haven't found anything for windows for closing.
You can try
command <nul
which basically means "take any input from the NUL device (as an infinite source of "CRLF"'s). This works as long as command takes its input from STDIN (like the pause command) and doesn't flush the input buffer (like the choice command)
If you need textual input (like the set /p command), you need another approach:
echo inputtext|command
From this question: bash - automatically capture output of last executed command into a variable I used this command:
PROMPT_COMMAND='LAST="`cat /tmp/x`"; exec >/dev/tty; exec > >(tee /tmp/x)'
It works, but when I use Vim I get this:
# vim
Vim: Warning: Output is not to a terminal
Then Vim opens. But it takes a while. Is there a way to get rid of this message and the slowdown?
Also when I list dir and I echo $LAST it removes the return lines (\n). Is there a way to keep the return lines (\n)?
I think what you ask for is hard do achieve. Vim tests if the output is a terminal. The command you've provided redirects the output to the tee command. tee saves its input (which also menans: command's output) to the file and outputs it to the terminal. But vim knows nothing about it. It only knows its output is not a terminal. So it outputs warning. And from the vim's source code:
[...]
if (scriptin[0] == NULL)
ui_delay(2000L, TRUE);
TIME_MSG("Warning delay");
which means this redirection will always get you 2 seconds delay.
Also, for example, man vim command will not work with such redirections, because terminal output has some attributest (e.g. width and height) which generic file hasn't. So... it won't work.
Which command in Windows command script (.cmd) accepts pipe (so, no error "The Process tried to write to a nonexistent pipe." generated), but generates no output itself, including output to StdErr? I need to not touch normal StdErr output (keep in mind, pipe transports only StdOut). I can't use null device, due to it's not installed in the system.
For example, command|rem generates mentioned error. But I want no error output, except generated by command, so rem is not suitable command for needed purpose.
Main aim is the script speed. So, don't offer extensive constructions, please.
should be break(or set/p= ?) as it is internal command prompt command (i.e. no external process started ) and generally do nothing.Though I suppose if you are searching for executable packed with the windows answer will be different.
The cd . command is what you are looking for. I used it to create empty files. This way, command | cd . works and echo Hello >&2 | cd . show "Hello" in the screen! This works as a filter that just blocks Stdout (interesting).
While debugging I want to display console output both on console and save a backup in file.
Windows doesn't have tee, but you can add one. Say the folder is c:\bin\ and it works fine. And I have added it into system's PATH.
Problem is setting "[ ]| tee[.exe] output.txt" or " | tee[.exe] output.txt" won't work -- the output.txt is just nowhere to be found. I also tried to add the c:\bin\ path explicitly in VC Directories or environment under debugging and merge environment to be yes.
"> output.txt" works fine.
Anyone has any idea how I can resolve this? Many thanks!
I assume that you're putting the | tee.exe output.txt string in the project property "Debugging | Command Argument".
Unfortunately, that property only supports the redirection operators, not the pipe operator. If you have the | tee.exe output.txt string in the preoperty and run a program that dumps the command line arguments, you'll see that that information is just passed on as the arguments. The "Debugging | Command Argument" doesn't actually get processed by a full-fledged shell (such as cmd.exe) - it's just the IDE supporting some simple redirection (actually, it seems to support more than I expected):
From http://msdn.microsoft.com/en-us/library/kcw4dzyf.aspx:
You can use the following redirection operators in this box:
< file
Reads stdin from file.
> file
Writes stdout to file.
>> file
Appends stdout to file.
2> file
Writes stderr to file.
2>> file
Appends stderr to file.
2> &1
Sends stderr (2) output to same location as stdout (1).
1> &2
Sends stdout (1) output to same location as stderr (2).
You can have a limited version of what you're looking for by redirecting the program's output to a file using >> and using a tail-f command to display whatever gets added to the file. If you do this you'll probably want to call setvbuf( stdout, NULL, _IONBF, 0 ) first thing in main() so that I/O is unbuffered. Otherwise tail -f won't see it until the buffer gets flushed, and I imagine that you'd like to see each output operation as it occurs.
Another option is to crank the console window's "Screen Buffer Height" property up to a large number - one of the first things I do when I get a new Windows machine is set that value to 3000 or so - then debug the program normally and copy/paste the contents of the console window before it closes.
You better NOT use printf for this purpose. Instead, write your own function; taking formatted-input, like printf - having variable number of arguments (...). That function will use printf to display on console, get the buffer written on file, would send to output to debug window and all. You may customize it depending on Debug/Release build.
It may go like (may have some minor mistakes):
void PrintDebuggingInfo(const char* pFormatString, ...)
{
va_list arguments;
char OutputString[1024];
va_start(pFormatString, argument);
vsprintf(OutputString, pFormatString, argument); // Generate string
// Now use `OutputString` as you wish!
}
You may use other variant of vsprintf. Infact all formatted-functions use this function only!
Okay, here's a toughie-- I'm capturing the output of cmd.exe just fine, reading from the pipe, yadda yadda yadda, but then a line in the cmd.exe batch file has the audacity to do:
dir err.txt >zz
.. that is, it's redirecting the output of the dir command, which is an internal command inside cmd.exe.
Problem is, this breaks my capturing of output! I can't get anything from cmd.exe after that point.
Apparently to redirect standard output, it closes it, or somehow breaks it, and makes a new stdout to redirect the output. And it never restores the old stdout handle.
Any ideas of how to track this output?
If you are allowed to modify the batch file, you may replace the inner redirection by a TEE command.
There are several ports to Windows (just google "windows command tee").
From Wikipedia:
In computing, tee is a command in various command-line interpreters (shells)
such as Unix shells, 4DOS/4NT and Windows PowerShell, which displays or pipes
the output of a command and copies it into a file or a variable
you should call dir err.txt in a separate process. try call dir err.txt >zz