56

I'm running an application on the command prompt or a Git shell, and I would like to get the output into Notepad, for easier review and editing later on.

I tried the following, but I always get an empty instance of Notepad:

diff file1.txt file2.txt | notepad

I'm aware that I can redirect the output to another file and then open the file in Notepad. I'd like to avoid the extra step, because I'm just used to piping into Vim or less on non-Windows systems.

Oliver Salzburg
  • 89,072
  • 65
  • 269
  • 311

12 Answers12

68

From what I can tell, there is no way to directly pipe into Notepad.

However, you can pipe into clip and then paste in notepad, like so:

 diff file1.txt file2.txt | clip && notepad

Then just press Ctrl+V in Notepad.

Oliver Salzburg
  • 89,072
  • 65
  • 269
  • 311
33

Consider using Vim, or in your case gVim if you prefer a graphical environment.

You can then pipe into it with a single hyphen as an argument, which instructs Vim/gVim to read from standard input.

diff file1.txt file2.txt | gvim -
10

here's a short Windows program that does it properly (without clobbering the clipboard). It should be adaptable to PowerShell, and I might update this answer if I get the time, but you can also just use that program directly.

Well, how about PowerShell? No need to install another application. Unfortunately, you will need to create a script file somewhere in your PATH...

Short version you can use

If you create a batch file (e.g. ShowInNotepad.bat) with the following contents and place it in your PATH somewhere:

@echo off
clip
powershell -Command $process = Start-Process -PassThru notepad;$SW_SHOW = 5;$sig = '[DllImport("""user32.dll""")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);';Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32;[Win32.NativeMethods]::ShowWindow($process.Id, $SW_SHOW) ^| Out-Null;Add-Type -AssemblyName System.Windows.Forms;[System.Windows.Forms.SendKeys]::SendWait('^^V');

you can then just call echo blah | ShowInNotepad from anywhere!

Note that this does assume that you're using a recent-ish version of Windows (Vista+) and have not disabled PowerShell or uninstalled the .NET framework. In other words, a default Windows installation will work.


Lengthy explanation and alternatives

The easiest way I can think of is to automate the paste (Ctrl+V) action. Which at least one other answer is already doing, but that one uses AHK - you might have better luck getting PowerShell to work in a locked-down corporate environment.

Let's get on with the script, yea?

#start notepad, get process object (to get pid later)
$process = Start-Process -PassThru notepad;

# activate Notepad window
# based on http://stackoverflow.com/a/4994020/1030702
# SW_SHOW activates and shows a window http://msdn.microsoft.com/en-us/library/windows/desktop/ms633548%28v=vs.85%29.aspx
$SW_SHOW = 5;
$sig = '[DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);';
Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32;
[Win32.NativeMethods]::ShowWindow($process.Id, $SW_SHOW) | Out-Null;

# send a "Ctrl+V" keystroke to the active window
# from http://stackoverflow.com/a/17851491/1030702
Add-Type -AssemblyName System.Windows.Forms;
[System.Windows.Forms.SendKeys]::SendWait('^V');

It's pretty straightforward, so I won't bother explaining the script more than the comments already do.

Usage

To use it, you just need to place the script in a .ps1 file (e.g. ShowInNotepad.ps1), place it somewhere in your PATH and then call powershell ShowInNotepad.ps1 after placing the text you want to display in the clipboard.

Example:

echo blah | clip && powershell ShowInNotepad.ps1

Unfortunately, executing PowerShell scripts can sometimes be difficult (execution policies and all). Therefore, I've condensed this script to a one-liner you can call directly from the Command Prompt, or even place into a batch file:

powershell -Command $process = Start-Process -PassThru notepad;$SW_SHOW = 5;$sig = '[DllImport("""user32.dll""")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);';Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32;[Win32.NativeMethods]::ShowWindow($process.Id, $SW_SHOW) ^| Out-Null;Add-Type -AssemblyName System.Windows.Forms;[System.Windows.Forms.SendKeys]::SendWait('^^V');

If you create a batch file (e.g. ShowInNotepad.bat) with the following contents and place it in your PATH somewhere:

@echo off
clip
powershell -Command $process = Start-Process -PassThru notepad;$SW_SHOW = 5;$sig = '[DllImport("""user32.dll""")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);';Add-Type -MemberDefinition $sig -name NativeMethods -namespace Win32;[Win32.NativeMethods]::ShowWindow($process.Id, $SW_SHOW) ^| Out-Null;Add-Type -AssemblyName System.Windows.Forms;[System.Windows.Forms.SendKeys]::SendWait('^^V');

you can then just call echo blah | ShowInNotepad from anywhere!

Bob
  • 63,170
5

This is totally possible; I just tried it. I'm assuming Notepad is set to open txt files by default:

diff file1.txt file2.txt > output.txt && start output.txt && timeout /T 3 && del output.txt

OK, you're technically creating a file, but it doesn't get saved.

Piping into more is also an option.

Casey
  • 302
5

How about using AutoHotkey?

Save the following as stdin.ahk and put it in your AutoHotkey directory:

StdIn(max_chars=0xfff)
{
    static hStdIn=-1
    ; The following is for vanilla compatibility
    ptrtype := (A_PtrSize = 8) ? "ptr" : "uint"

    if (hStdIn = -1)
    {
        hStdIn := DllCall("GetStdHandle", "UInt", -10,  ptrtype) ; -10=STD_INPUT_HANDLE
        if ErrorLevel
            return 0
    }

    max_chars := VarSetCapacity(text, max_chars*(!!A_IsUnicode+1), 0)

    ret := DllCall("ReadFile"
        ,  ptrtype, hStdIn        ; hFile
        ,  "Str", text          ; lpBuffer
        , "UInt", max_chars*(!!A_IsUnicode+1)     ; nNumberOfBytesToRead
        , "UInt*", bytesRead    ; lpNumberOfBytesRead
        ,  ptrtype, 0)            ; lpOverlapped

    return text
}

loop 
{
    sleep 100 ;wait for data
    Buffer:=StdIn()
    PipeText:=PipeText . Buffer
    IfWinActive Untitled - Notepad
        {
        SendInput {Raw}%PipeText%
        PipeText = 
        }
}

Then the command line:

ping -t www.google.com | AutoHotkeyA32.exe stdin.ahk

Pipes the output of the command into Notepad, so long as the window is open and titled Untitled - Notepad. In the event that the window is not active then it will cheerfully buffer in the background until the window is active. You can even go away to another program and it will carry on buffering once more.

This seems to die when the program outputting to our standard input dies though...

(For information, the stdin() code was shamelessly half-inched from here)

Mokubai
  • 95,412
1

Here is an ugly, but effective way to accomplish this:

$OutputString = 'Hello World'
$WScript = New-Object -ComObject 'wscript.shell'
$WScript.Run('notepad.exe') | Out-Null
do 
    {
    Start-Sleep -Milliseconds 100
    }
until ($WScript.AppActivate('notepad'))
$WScript.SendKeys($OutputString)

Just be sure to only send text output. Other data will potentially be interpreted as control characters (CTRL, ALT, DEL, etc.).

Sean
  • 11
1

Yet another solution to consider! VS Code can receive piped input also, if you now use this instead of Notepad. I noticed this in V1.41, don't know when it was implemented.

In this example:

diff file1.txt file2.txt | code -

Note the dash as a parameter to Code.

rwg
  • 131
1

10 years late on this answer, If you have VS Code installed the command would look like this:

<command> | code -

In my case,

pip list | code - 

works on both cmd and powershell

rwg
  • 131
0

Here's a couple of VBScript based solutions that may work (although .. they rely a little on apps opening on time):

pipe2key.vbs - opens the application specified as the first argument, and then sends StdIn as keystrokes to it. Needs to be used with cscript.exe as wscript does not provide StdIn access. Probably quite slow for long documents - but won't clobber the clipboard

Set inPipe=wScript.StdIn
Set wShell=wScript.CreateObject("wscript.shell")
wShell.Run wScript.Arguments(0), 5 ' Execute specified app, foreground it's window
wScript.Sleep 500 ' Wait for app to load
KeysToEscape="{}[]()^+%"
KeysToDrop=vbLf
While Not inPipe.AtEndOfStream
    keyChar=inPipe.Read(1)
    If InStr(KeysToDrop, keyChar) = 0 Then
        If InStr(KeysToEscape, keyChar) > 0 Then
            wShell.SendKeys "{" & keyChar & "}"
        Else
            wShell.SendKeys keyChar
        End If
    End If
Wend

Example usage: diff file1.txt file2.txt | cscript pipe2key.vbs notepad.exe

Or, pasteinto.vbs. Automates the CTRL-V operation after launching an app (thus uses the 'clip' command as mentioned in previous answers). Considerably faster and cleaner (in my opinion) than pipe2key.vbs, but the process will overwrite the clipboard

Set wShell=wScript.CreateObject("wscript.shell")
wShell.Run wScript.Arguments(0), 5 ' Execute specified app, foreground it's window
wScript.Sleep 500 ' Wait for app to load
wShell.SendKeys "^v"

Example usage: diff file1.txt file2.txt | clip && pasteinto notepad.exe

-1

Something like this "might" work.

Aw, ya didn't realize this is something you'd be doing manually each time (from the sounds of it). You might be able to make some sort of macro or something to do it for you each time to speed up the process. Not sure on that one.

diff file1.txt file2.txt > file.txt | sleep 1 | notepad.exe file.txt | rm file.txt

It would have to finish writing the diff contents to file.txt in order for it to load the entirety of the diff operation which I'm not sure if it'll do. There might be a way to pause somehow between the pipe operation if that is the case.

Codezilla
  • 964
-2

My language is not English so sorry for mistakes.

I think u can't directly put the output into the open Notepad. May be I am wrong about it. You have to create a file with the output in it in order to work on it. The command tee can pipe the output to two or may be more commands or files in the same time.

man tee

Don't forget to use >> instead > when you redurect the output into the file. The > will overwrite the file, >> will add the output after whatever has already in that file.

-3

You can't, Notepad is too limited for this! Better yet... install Cygwin and workaround all this "lack of features" of Windows. You can then use the command you already know.

AFAIK, very few Windows program support pipelining, even worse for GUI programs.

You can try to open feature requests to one of the "windows tail" programs to add that.

higuita
  • 560