Como canalizar a saída do console diretamente para o Bloco de Notas?

47

Estou executando um aplicativo no prompt de comando ou no shell Git e gostaria de obter a saída no Bloco de Notas, para facilitar a revisão e edição mais tarde.

Tentei o seguinte, mas sempre recebo uma instância vazia do bloco de notas:

diff file1.txt file2.txt | notepad

Estou ciente de que posso redirecionar a saída para outro arquivo e abrir o arquivo no Bloco de Notas. Gostaria de evitar a etapa extra, porque estou acostumado a usar o Vim ou menos em sistemas não Windows.

Der Hochstapler
fonte
2
Obviamente, você também pode canalizar moreno Windows.
Gabe
1
Por que não enviar para arquivo e simplesmente executar o novo caminho de arquivo com shell - deixe o sistema operacional lidar com o aplicativo de apresentação. Será que ela tem que ser o bloco de notas?
Gusdor
@ Gusdor A questão é principalmente sobre como evitar criar um arquivo (temporário).
Der Hochstapler
1
A funcionalidade do bloco de notas é tão limitada que você quase não pode fazer nada com ela. Como você está familiarizado vim, por que não instalá-lo?
Siyuan Ren
@ CR Eu poderia fazer isso em meus próprios computadores, mas trabalho regularmente em computadores que não possuo. Portanto, é útil saber quais opções existem sem instalar software de terceiros.
Der Hochstapler

Respostas:

63

Pelo que sei, não há como entrar diretamente no Bloco de Notas.

No entanto, você pode canalizar clipe colar no bloco de notas, assim:

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

Em seguida, pressione Ctrl+ Vno bloco de notas.

Der Hochstapler
fonte
3
Funcionaria se você redirecionasse a saída para file3.txt e depois && notepad file3.txt?
Konerak
4
@Konerak Sim, isso iria funcionar e que é exatamente o que eu estava tentando evitar (como explicado na questão);)
Der Hochstapler
32

Considere usar o Vim ou, no seu caso, o gVim, se você preferir um ambiente gráfico.

Em seguida, você pode inserir nele com um único hífen como argumento, o que instrui o Vim / gVim a ler da entrada padrão.

diff file1.txt file2.txt | gvim -
Benjamin Goodacre
fonte
1
instalá-lo, o bloco de notas é realmente limitado, você não pode usá-lo para isso. você pode até mesmo tê-lo em aplicativos portáteis: portableapps.com/apps/development/gvim_portable
higuita
3
Também é possível fazer isso de dentro do vim::%!diff file1.txt file2.txt
SlightlyCuban
@TankorSmash Eu também, mas esse não é o ponto da questão;) Para mais discussões a favor e contra a respeito do vim (ou qualquer outro tópico), por favor, encontre-me no Super User Chat , os tópicos de comentários não são uma ótima maneira de conversar. :(
Der Hochstapler
1
@OliverSalzburg Eu estava tentando sugerir que o gvim está disponível no Windows, pois entendi que seu comentário significava que não estava. Eu estava errado.
TankorSmash
-é freqüentemente usado para significar "ler de stdin", portanto, isso não é estritamente limitado a vim. Outros editores usam -i(por exemplo kate).
Bakuriu
8

Aqui está um pequeno programa do Windows que faz isso corretamente (sem sobrecarregar a área de transferência). Ele deve ser adaptável ao PowerShell, e eu posso atualizar esta resposta se eu conseguir o tempo, mas você também pode usar esse programa diretamente.

Bem, e o PowerShell? Não há necessidade de instalar outro aplicativo. Infelizmente, você vai precisar criar um arquivo de script em algum lugar em sua PATH...

Versão curta que você pode usar

Se você criar um arquivo em lotes (por exemplo ShowInNotepad.bat) com o seguinte conteúdo e o colocar em PATHalgum lugar:

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

você pode simplesmente ligar echo blah | ShowInNotepadde qualquer lugar!

Note que este não assumir que você está usando uma versão recente-ish do Windows (Vista +) e não tivesse desativado PowerShell ou desinstalado o .NET framework. Em outras palavras, uma instalação padrão do Windows funcionará.


Longas explicações e alternativas

A maneira mais fácil de pensar é automatizar a ação colar ( Ctrl+ V). Qual pelo menos uma outra resposta já está em andamento, mas essa usa o AHK - você pode ter melhor sorte em fazer com que o PowerShell funcione em um ambiente corporativo bloqueado.

Vamos continuar com o roteiro, sim?

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

É bem direto, então não vou me preocupar em explicar o script mais do que os comentários já fazem.

Uso

Para usá-lo, você só precisa colocar o script em um .ps1arquivo (por exemplo ShowInNotepad.ps1), colocá-lo em algum lugar do seu PATHe depois ligar powershell ShowInNotepad.ps1depois de colocar o texto que deseja exibir na área de transferência.

Exemplo:

echo blah | clip && powershell ShowInNotepad.ps1

Infelizmente, às vezes, a execução de scripts do PowerShell pode ser difícil (políticas de execução e tudo). Portanto, condensamos esse script em uma linha única que você pode chamar diretamente no prompt de comando ou até colocar em um arquivo em 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');

Se você criar um arquivo em lotes (por exemplo ShowInNotepad.bat) com o seguinte conteúdo e o colocar em PATHalgum lugar:

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

você pode simplesmente ligar echo blah | ShowInNotepadde qualquer lugar!

Prumo
fonte
Honestamente, se você estiver escrevendo um script PS, basta criar um arquivo com um nome Guid na pasta de arquivos temporários e excluí-lo quando terminar. Automatizar a pasta parece muito quebradiço (como se você perder o foco na hora errada ou algo assim)?
Casey
@emodendroket Infelizmente, quando você tenta forçar a entrada de fluxo em um programa que não o suporta nativamente, nada é realmente limpo. A criação de um arquivo temporário tem suas próprias desvantagens (menores): na verdade, você não recebe um "novo arquivo", portanto a Savesaída e os comportamentos modificados são diferentes. Além de substituir o próprio bloco de notas ou injetar diretamente o texto em seu controle de edição, não há muitas outras opções. Obviamente, esse método tem a desvantagem do conteúdo da área de transferência (embora esses sejam supostamente efêmeros). Não acho que perder o foco seja uma questão importante; é uma ...
Bob
... condição de corrida extremamente improvável (entre as ShowWindowteclas e o envio). E esse método requer um pouco mais de configuração (criando o arquivo de script) para ser usado, sim.
Bob
5

Que tal usar o AutoHotkey ?

Salve o seguinte como stdin.ahke coloque-o no diretório 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 = 
        }
}

Então a linha de comando:

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

Canaliza a saída do comando no Bloco de Notas, desde que a janela esteja aberta e com o título Untitled - Notepad. No caso de a janela não estar ativa, ela ficará em buffer em segundo plano até que a janela esteja ativa. Você pode até ir para outro programa e ele continuará armazenando o buffer novamente.

Isso parece morrer quando o programa que produz a nossa entrada padrão morre ...

(Para obter informações, o código stdin () foi descaradamente semicircular daqui )

Mokubai
fonte
...Uau. Se você for para esse ponto, é melhor escrever um programa compilado inteiro! Provavelmente seja mais eficiente também: P Ainda assim, vote no esforço.
Bob
Voto negativo de mim, estou com medo. Superengenharia no sentido clássico. Quem é a versão que controla esse script? A autohotkey precisa de uma licença para aplicativos comerciais? Quem monitora isso?
Gusdor
7
@Gusdor Toda a Internet está cheia de trechos de código não controlados por versão. Temos o benefício de ter um histórico de revisões para este post. Também não vejo como o licenciamento comercial tem algo a ver com essa pergunta. O AHK é usado por muitas pessoas, e elas podem achar essa resposta útil.
slhck
@slhck Eu estava simplesmente comentando as armadilhas dessa solução, não sua validade.
Gusdor
@slhck: O conteúdo deste site é coberto pelo Creative Commons.
Brian
4

Isso é totalmente possível; Eu apenas tentei. Estou assumindo que o Bloco de notas está definido para abrir arquivos txt por padrão:

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

OK, você está tecnicamente criando um arquivo, mas ele não é salvo.

Piping em mais também é uma opção.

Casey
fonte
4
Tenha cuidado - se você já tem um, output.txtisso vai atrapalhar. Marginalmente mais seguro seria usar %temp%/somerandomstring.txt.
Bob
É mais seguro salvar um arquivo de saída no diretório temp - dê uma olhada nesta resposta.
Lu55 11/11
1

Aqui está uma maneira feia, mas eficaz de fazer isso:

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

Apenas certifique-se de enviar apenas a saída de texto. Outros dados serão potencialmente interpretados como caracteres de controle (CTRL, ALT, DEL, etc.).

Sean
fonte
0

Aqui estão algumas soluções baseadas em VBScript que podem funcionar (embora .. elas dependam um pouco dos aplicativos que são abertos a tempo):

pipe2key.vbs - abre o aplicativo especificado como o primeiro argumento e envia StdIn como pressionamentos de tecla. Precisa ser usado com o cscript.exe, pois o wscript não fornece acesso ao StdIn. Provavelmente bem devagar para documentos longos - mas não atrapalha a área de transferência

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

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

Ou, cole em.vbs. Automatiza a operação CTRL-V após o lançamento de um aplicativo (portanto, usa o comando 'clip' conforme mencionado nas respostas anteriores). Consideravelmente mais rápido e limpo (na minha opinião) do que pipe2key.vbs, mas o processo substituirá a área de transferência

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"

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

Jason Musgrove
fonte
-1

Algo como esse "pode" funcionar.

Ah, você não percebeu que isso é algo que você faria manualmente todas as vezes (pelo que parece). Você pode criar algum tipo de macro ou algo para fazer isso a cada vez para acelerar o processo. Não tenho a certeza sobre isso.

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

Teria que terminar de escrever o conteúdo do diff no arquivo.txt para carregar toda a operação do diff, o que não tenho certeza se será. Pode haver uma maneira de fazer uma pausa de alguma forma entre a operação do tubo, se for esse o caso.

Codezilla
fonte
5
O objetivo é não criar um arquivo temporário e eu tenho certeza que há algo errado com sua sintaxe lá;)
Der Hochstapler
"para facilitar a revisão e edição mais tarde", achei que era isso que você queria? E como Rev1.0 apontou e emendou, ele funciona. Isto é para dos, no entanto, não tenho certeza se o cygwin teria os mesmos resultados.
Codezilla
3
Eu acho que porque um & seria adequado, pois na verdade nada precisa ser "canalizado" entre essas chamadas.
Rev1.0
3
@ Rev1.0 Correto. &, &&E ||são os operadores para os comandos encadear. Todos os três se comportam de maneira diferente na maneira como procedem se um comando gerar um valor de retorno diferente de 0. |é completamente diferente, pois é usado para canalizar a saída de um programa para outro. O resultado pode ser o que você queria, mas o uso de um dos operadores de encadeamento torna a intenção mais clara, porque nenhuma tubulação real é desejada nesse exemplo. Para referência adicional: microsoft.com/resources/documentation/windows/xp/all/proddocs/...
Der Hochstapler
1
@ Codezilla Acho que a ideia no meu post é bastante semelhante à sua, mas é uma sintaxe válida para o prompt de comando.
Casey
-3

Meu idioma não é o inglês, desculpe-me por erros.

Eu acho que você não pode colocar diretamente a saída no bloco de notas aberto. Pode ser que eu esteja errado sobre isso. Você precisa criar um arquivo com a saída para poder trabalhar nele. O comando tee pode canalizar a saída para dois ou pode haver mais comandos ou arquivos ao mesmo tempo.

homem tee

Não se esqueça de usar >> em vez disso> ao redirecionar a saída para o arquivo. O> substituirá o arquivo, >> adicionará a saída depois do que já estiver nesse arquivo.

user338167
fonte
1
teegeralmente não está disponível no Windows e, mesmo que estivesse, não ajudaria com esse problema.
Der Hochstapler
-4

Você não pode, o Bloco de Notas é muito limitado para isso! Melhor ainda ... instale o Cygwin e contorne toda essa "falta de recursos" do Windows. Você pode usar o comando que você já conhece.

AFAIK, muito poucos programas do Windows suportam pipelining, ainda pior para programas de GUI.

Você pode tentar abrir solicitações de recursos para um dos programas "windows tail" para adicionar isso.

higuita
fonte
2
Eu já uso o cygwin. Este é realmente um problema específico para interação com o Bloco de Notas.
Der Hochstapler
1
@emodendroket algumas vezes as pessoas usam a ferramenta errada para um trabalho ... e para quase todo o caso, o bloco de notas é a ferramenta errada, é tão simples e limitado :)
higuita
1
@higuita Sou um usuário dedicado do Emacs, mas às vezes o Notepad é a melhor ferramenta para o que eu quero fazer.
Casey