¿Cómo puedo canalizar la salida de la consola directamente al Bloc de notas?

47

Estoy ejecutando una aplicación en el símbolo del sistema o un shell Git , y me gustaría obtener la salida en el Bloc de notas, para una revisión y edición más fáciles más adelante.

Intenté lo siguiente, pero siempre obtengo una instancia vacía de Bloc de notas:

diff file1.txt file2.txt | notepad

Soy consciente de que puedo redirigir la salida a otro archivo y luego abrir el archivo en el Bloc de notas. Me gustaría evitar el paso adicional, porque estoy acostumbrado a conectarme a Vim o menos en sistemas que no son Windows.

Der Hochstapler
fuente
2
Por supuesto, también puede canalizar moreen Windows.
Gabe
1
¿Por qué no canalizar al archivo y simplemente ejecutar la nueva ruta del archivo? Deje que el sistema operativo maneje la aplicación de presentación. ¿ Tiene que ser un bloc de notas?
Gusdor
@Gusdor La pregunta es principalmente sobre cómo evitar crear un archivo (temporal).
Der Hochstapler
1
La funcionalidad del Bloc de notas es tan limitada que apenas puede hacer nada con ella. Ya que estás familiarizado vim, ¿por qué no solo instalarlo?
Siyuan Ren
@CR Podría hacerlo en mis propias computadoras, pero trabajo regularmente en computadoras que no tengo. Por lo tanto, es útil saber qué opciones hay sin instalar software de terceros.
Der Hochstapler

Respuestas:

63

Por lo que puedo decir, no hay forma de canalizar directamente en el Bloc de notas.

Sin embargo, puede canalizar clipy luego pegar en el bloc de notas, así:

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

Luego simplemente presione Ctrl+ Ven el Bloc de notas.

Der Hochstapler
fuente
3
¿Funcionaría si redirigiera la salida a file3.txt y luego && notepad file3.txt?
Konerak
44
@Konerak Sí, eso funcionaría y eso es exactamente lo que estaba tratando de evitar (como se explica en la pregunta);)
Der Hochstapler
32

Considere usar Vim , o en su caso gVim si prefiere un entorno gráfico.

Luego puede canalizarlo con un solo guión como argumento, que le indica a Vim / gVim que lea desde la entrada estándar.

diff file1.txt file2.txt | gvim -
Benjamin Goodacre
fuente
1
instálelo, el Bloc de notas es realmente limitado, no puede usarlo para esto. incluso puede tenerlo en aplicaciones portátiles
higuita
3
También puede hacer esto desde vim::%!diff file1.txt file2.txt
SlightlyCuban
@TankorSmash Yo también, pero ese no es el punto de la pregunta;) Para más discusiones a favor y en contra de vim (o cualquier otro tema), por favor encuéntreme en Super User Chat , los hilos de comentarios no son una excelente manera de tener una conversación :(
Der Hochstapler
1
@OliverSalzburg Intentaba sugerir que gvim está disponible en Windows, ya que entendí que tu comentario significaba que no lo estaba. Estaba equivocado.
TankorSmash
-a menudo se usa para significar "leer de stdin", por lo que esto no se limita estrictamente a vim. Uso de otros editores -i(p kate. Ej .).
Bakuriu
8

Aquí hay un breve programa de Windows que lo hace correctamente (sin golpear el portapapeles). Debería ser adaptable a PowerShell, y podría actualizar esta respuesta si tengo tiempo, pero también puede usar ese programa directamente.

Bueno, ¿qué tal PowerShell? No es necesario instalar otra aplicación. Desafortunadamente, usted tendrá que crear un archivo de script en alguna parte en su PATH...

Versión corta que puedes usar

Si crea un archivo por lotes (por ejemplo ShowInNotepad.bat) con los siguientes contenidos y lo coloca en su PATHlugar:

@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');

¡entonces puedes llamar echo blah | ShowInNotepaddesde cualquier lugar!

Tenga en cuenta que esto no suponerse que se está utilizando una versión reciente-ish de Windows (Vista +) y no se ha desactivado PowerShell o desinstalado el marco .NET. En otras palabras, una instalación predeterminada de Windows funcionará.


Explicación larga y alternativas

La forma más fácil que se me ocurre es automatizar la acción de pegar ( Ctrl+ V). Lo que al menos otra respuesta ya está haciendo, pero esa usa AHK: es posible que tenga más suerte al hacer que PowerShell funcione en un entorno corporativo bloqueado.

Sigamos con el guión, ¿sí?

#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');

Es bastante sencillo, por lo que no me molestaré en explicar el guión más de lo que ya lo hacen los comentarios.

Uso

Para usarlo, solo necesita colocar el script en un .ps1archivo (por ejemplo ShowInNotepad.ps1), colocarlo en algún lugar de su PATHy luego llamar powershell ShowInNotepad.ps1después de colocar el texto que desea mostrar en el portapapeles.

Ejemplo:

echo blah | clip && powershell ShowInNotepad.ps1

Desafortunadamente, ejecutar scripts de PowerShell a veces puede ser difícil (políticas de ejecución y todo). Por lo tanto, he condensado este script en una línea que puede llamar directamente desde el Símbolo del sistema, o incluso colocarlo en un archivo por lotes:

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');

Si crea un archivo por lotes (por ejemplo ShowInNotepad.bat) con los siguientes contenidos y lo coloca en su PATHlugar:

@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');

¡entonces puedes llamar echo blah | ShowInNotepaddesde cualquier lugar!

Mover
fuente
Honestamente, si vas a escribir un script PS, simplemente crearía un archivo con un nombre Guid en la carpeta del archivo temporal y lo eliminaría cuando terminara. La automatización de la pasta parece demasiado frágil (¿qué pasa si pierdes el foco en el momento equivocado o algo así?)
Casey
@emodendroket Desafortunadamente, cuando intentas forzar la entrada de flujo en un programa que no lo admite de forma nativa, nada es realmente limpio. La creación de un archivo temporal tiene sus propios inconvenientes (menores): en realidad no se obtiene un "nuevo archivo", por lo que la Savesalida de los comportamientos modificados es diferente. Además de reemplazar el Bloc de notas o inyectar directamente el texto en su control de edición, no hay muchas otras opciones. Por supuesto, este método tiene el inconveniente de golpear el contenido del portapapeles (aunque de todos modos se supone que son efímeros). No creo que perder el enfoque sea un problema importante; es un ...
Bob
... condición de carrera extremadamente improbable (entre el ShowWindowenvío y las pulsaciones de teclas). Y este método requiere un poco más de configuración (crear el archivo de script) para usar, sí.
Bob
5

¿Qué tal el uso de AutoHotkey ?

Guarde lo siguiente como stdin.ahky póngalo en su directorio AutoHotkey:

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 = 
        }
}

Luego la línea de comando:

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

Canaliza la salida del comando en el Bloc de notas, siempre que la ventana esté abierta y titulada Untitled - Notepad. En el caso de que la ventana no esté activa, se almacenará en el búfer en segundo plano hasta que la ventana esté activa. Incluso puede ir a otro programa y continuará almacenando en el búfer una vez más.

Sin embargo, esto parece morir cuando el programa que sale a nuestra entrada estándar muere ...

(Para información, el código stdin () fue descaradamente medio incrustado desde aquí )

Mokubai
fuente
...Guau. Si vas a llegar a ese punto, ¡también podrías escribir un programa compilado completo! Probablemente sea más eficiente también: P Vota por el esfuerzo.
Bob
Voto abajo de mí, tengo miedo. La sobreingeniería en el sentido clásico. ¿Quién es la versión que controla este script? ¿Autohotkey necesita una licencia para aplicaciones comerciales? ¿Quién monitorea eso?
Gusdor
77
@Gusdor Toda la Internet está llena de fragmentos de código no controlados por la versión. Tenemos la ventaja de tener incluso un historial de revisiones para esta publicación. Tampoco veo cómo las licencias comerciales tienen algo que ver con esta pregunta. AHK es utilizado por muchas personas, y pueden encontrar esta respuesta útil.
slhck
@slhck Simplemente estaba comentando las trampas de esta solución, no su validez.
Gusdor
@slhck: el contenido de este sitio está cubierto por Creative Commons.
Brian
4

Esto es totalmente posible; Solo lo intenté. Supongo que Notepad está configurado para abrir archivos txt de forma predeterminada:

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

OK, técnicamente estás creando un archivo, pero no se guarda.

Ir a más es también una opción.

Casey
fuente
44
Tenga cuidado: si ya tiene un output.txtesto, lo golpeará. Marginalmente más seguro sería usar %temp%/somerandomstring.txt.
Bob
Es más seguro guardar un archivo de salida en el directorio temporal; eche un vistazo a esta respuesta.
Lu55
1

Aquí hay una forma fea pero efectiva de lograr esto:

$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)

Solo asegúrese de enviar solo salida de texto. Otros datos se interpretarán potencialmente como caracteres de control (CTRL, ALT, DEL, etc.).

Sean
fuente
0

Aquí hay un par de soluciones basadas en VBScript que pueden funcionar (aunque ... dependen un poco de las aplicaciones que se abren a tiempo):

pipe2key.vbs: abre la aplicación especificada como primer argumento y luego le envía StdIn como pulsaciones de teclas. Debe usarse con cscript.exe ya que wscript no proporciona acceso StdIn. Probablemente bastante lento para documentos largos, pero no golpeará el portapapeles

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

Ejemplo de uso: diff file1.txt file2.txt | cscript pipe2key.vbs notepad.exe

O pasteinto.vbs. Automatiza la operación CTRL-V después de iniciar una aplicación (por lo tanto, utiliza el comando 'clip' como se menciona en las respuestas anteriores). Considerablemente más rápido y limpio (en mi opinión) que pipe2key.vbs, pero el proceso sobrescribirá el portapapeles

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"

Ejemplo de uso: diff file1.txt file2.txt | clip && pasteinto notepad.exe

Jason Musgrove
fuente
-1

Algo como este "podría" funcionar.

Aw, no te diste cuenta de que esto es algo que harías manualmente cada vez (por lo que parece). Es posible que pueda hacer algún tipo de macro o algo que lo haga por usted cada vez para acelerar el proceso. No estoy seguro de eso.

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

Tendría que terminar de escribir el contenido de diff en file.txt para que cargue la totalidad de la operación de diff, lo que no estoy seguro de si lo hará. Puede haber una manera de pausar de alguna manera entre la operación de tubería si ese es el caso.

Codezilla
fuente
55
El objetivo es no crear un archivo temporal y estoy bastante seguro de que hay algo mal con su sintaxis allí;)
Der Hochstapler
"para una revisión y edición más fácil más adelante" ¿Pensé que eso era lo que querías? Y como Rev1.0 señaló y modificó, funciona. Sin embargo, no estoy seguro de si Cygwin tendría los mismos resultados.
Codezilla
3
Supongo que un & sería adecuado ya que en realidad no hay nada que "canalizar" entre esas llamadas.
Rev1.0
3
@ Rev1.0 Correcto. &, &&y ||son operadores para encadenar comandos juntos. Los 3 se comportan de manera diferente en cómo proceden si un comando genera un valor de retorno distinto de 0. |es completamente diferente ya que se utiliza para canalizar la salida de un programa a otro. El resultado podría ser lo que deseaba, pero el uso de uno de los operadores de encadenamiento aclara la intención, porque no se desea una tubería real en ese ejemplo. Para referencia adicional: microsoft.com/resources/documentation/windows/xp/all/proddocs/…
Der Hochstapler
1
@Codezilla Creo que la idea en mi publicación es bastante similar a la suya, pero es una sintaxis de símbolo del sistema válida.
Casey
-3

Mi idioma no es el inglés, así que lamento los errores.

Creo que no puede poner directamente la salida en el Bloc de notas abierto. Puede ser que me equivoque al respecto. Tiene que crear un archivo con la salida para poder trabajar en él. El comando tee puede canalizar la salida a dos o puede haber más comandos o archivos al mismo tiempo.

camiseta de hombre

No olvide usar >> en su lugar> cuando reduzca la salida al archivo. El> sobrescribirá el archivo, >> agregará la salida después de lo que ya haya en ese archivo.

usuario338167
fuente
1
teegeneralmente no está disponible en Windows e incluso si lo estuviera, no ayudaría con este problema.
Der Hochstapler
-4

No puedes, ¡el Bloc de notas es demasiado limitado para esto! Mejor aún ... instale Cygwin y solucione toda esta "falta de características" de Windows. Luego puede usar el comando que ya conoce.

AFAIK, muy pocos programas de Windows admiten la canalización, lo que es peor para los programas GUI.

Puede intentar abrir solicitudes de funciones a uno de los programas de "cola de Windows" para agregar eso.

higuita
fuente
2
Ya uso cygwin. Esto es realmente un problema específico para la interacción con el Bloc de notas.
Der Hochstapler
1
@emodendroket algunas veces la gente usa la herramienta equivocada para un trabajo ... y para casi cualquier caso, el bloc de notas es la herramienta equivocada, es tan simple y limitado :)
Higuita
1
@higuita Soy un usuario devoto de Emacs pero a veces el Bloc de notas es la mejor herramienta para lo que quiero hacer.
Casey