Як я можу передати консольний вихід безпосередньо на Блокнот?


47

Я запускаю додаток у командному рядку або оболонці Git , і я хотів би отримати висновок у Блокноті для більш легкого огляду та редагування згодом.

Я спробував таке, але завжди отримую порожній примірник Блокнота:

diff file1.txt file2.txt | notepad

Я знаю, що можу перенаправити вихід на інший файл, а потім відкрити файл у Блокноті. Я хотів би уникнути зайвого кроку, тому що я просто звик переходити на Vim або менше в системах, які не є Windows.


2
Звичайно, ви також можете підключитися до moreWindows.
Гейб

1
Чому б не передати файл і просто виконати оболонку нового шляху до файлу - нехай ОС обробляє презентаційну програму. Чи повинен це бути блокнот?
Гусдор

@Gusdor Питання стосується перш за все уникнення створення (тимчасового) файлу.
Der Hochstapler

1
Функціональність блокнота настільки обмежена, що з ним навряд чи можна щось зробити. Оскільки ви знайомі vim, чому б не просто встановити його?
Сіюань Рен

@CR Я міг би це робити на своїх комп’ютерах, але регулярно працюю на комп’ютерах, якими я не володію. Тож корисно знати, які існують варіанти, не встановлюючи сторонне програмне забезпечення.
Der Hochstapler

Відповіді:


63

З того, що я можу сказати, немає ніякого способу безпосередньо потрапити в Блокнот.

Однак ви можете вставити в нього, clipа потім вставити його в блокнот:

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

Потім просто натисніть Ctrl+ Vу Блокноті.


3
Це спрацює, якщо ви будете перенаправляти вихід на file3.txt, а потім && notepad file3.txt?
Конерак

4
@Konerak Так, це спрацювало, і саме цього я намагався уникати (як пояснено у запитанні);)
Der Hochstapler

32

Подумайте про використання Vim або у вашому випадку gVim, якщо ви віддаєте перевагу графічному середовищу.

Потім ви можете ввести в нього аргумент одним дефісом як аргумент, який вказує Vim / gVim читати зі стандартного вводу.

diff file1.txt file2.txt | gvim -

1
встановіть його, Блокнот дійсно обмежений, ви не можете використовувати його для цього. ви навіть можете мати його в портативних програмах: portableapps.com/apps/development/gvim_portable
higuita

3
Можна також зробити це з vim::%!diff file1.txt file2.txt
SlightlyCuban

@TankorSmash Так, як і я, але це не сенс питання;) Для подальшої дискусії про v і con щодо vim (або будь-якої іншої теми), будь ласка, знайдіть мене в чаті Super User , нитки коментарів - це не відмінний спосіб вести розмову :(
Der Hochstapler

1
@OliverSalzburg Я намагався припустити, що gvim доступний у Windows, оскільки я зрозумів, що ваш коментар означає, що це не так. Я помилявся.
TankorSmash

-часто використовується для позначення "читати зі stdin", тому це не обмежується строго vim. Інші редактори використовують -i(наприклад kate).
Бакуріу

8

ось коротка програма Windows, яка робить це належним чином (не розтушовуючи буфер обміну). Він повинен бути адаптованим до PowerShell, і я можу оновити цю відповідь, якщо знайду час, але ви також можете просто скористатися цією програмою безпосередньо.

Ну, а як щодо PowerShell? Не потрібно встановлювати інший додаток. На жаль, вам буде потрібно створити файл сценарію в своєму PATH...

Коротка версія, яку ви можете використовувати

Якщо ви створюєте пакетний файл (наприклад ShowInNotepad.bat) із наступним вмістом і поміщаєте його у своє PATHкудись:

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

Ви можете просто зателефонувати echo blah | ShowInNotepadз будь-якого місця!

Зверніть увагу , що це дійсно припустити , що ви використовуєте останню іш версію Windows (Vista +) і не відключили PowerShell або деінсталювати рамки .NET. Іншими словами, буде встановлена ​​установка Windows за замовчуванням.


Тривале пояснення та альтернативи

Найпростіший спосіб, який я можу придумати, - це автоматизувати дію вставлення ( Ctrl+ V). Який хоча б ще один відповідь вже робить, але той, що використовує AHK - ви, можливо, матимете більше удачі змусити PowerShell працювати в зафіксованому корпоративному середовищі.

Давайте продовжимо сценарій, так?

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

Це досить просто, тому я не буду намагатися пояснювати сценарій більше, ніж коментарі.

Використання

Для його використання потрібно просто помістити скрипт у .ps1файл (наприклад ShowInNotepad.ps1), розмістити його десь у своєму, PATHа потім зателефонувати powershell ShowInNotepad.ps1після розміщення тексту, який потрібно відобразити у буфер обміну.

Приклад:

echo blah | clip && powershell ShowInNotepad.ps1

На жаль, виконання сценаріїв PowerShell іноді може бути складним (правила виконання та всі). Тому я сконденсував цей скрипт до однолінійного виклику, на який можна зателефонувати безпосередньо з командного рядка або навіть розмістити у пакетному файлі:

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

Якщо ви створюєте пакетний файл (наприклад ShowInNotepad.bat) із наступним вмістом і поміщаєте його у своє PATHкудись:

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

Ви можете просто зателефонувати echo blah | ShowInNotepadз будь-якого місця!


Чесно кажучи, якщо ви збираєтеся написати сценарій PS, я просто створив би файл із ім'ям Guid у папці temp file та видалив його, коли я закінчив. Автоматизація пасти видається занадто крихкою (як, наприклад, якщо ви втратите фокус у невідповідний час чи щось)?
Кейсі

@emodendroket На жаль, коли ви намагаєтеся примусити ввести потік в програму, яка не підтримує її, нічого не є справді чистим. Створення тимчасового файлу має свої (незначні) недоліки: ви насправді не отримуєте "новий файл", тому Saveвихід і зміна поведінки відрізняються. Окрім заміни самого Блокнота або безпосередньо введення тексту в його елемент керування редагуванням, існує не так багато інших варіантів. Звичайно, у цього методу є недолік вмісту буфера обміну клопоту (хоча вони, мабуть, є ефемерними). Я не думаю, що втрата уваги є головною проблемою; це ...
Боб

... вкрай малоймовірний стан перегонів (між ShowWindowнатисканням клавіш та відправленням). І цей спосіб вимагає трохи більше налаштування (створення файлу сценарію), щоб використовувати.
Боб

5

Як щодо використання AutoHotkey ?

Збережіть наступне як stdin.ahkі покладіть його у каталог 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 = 
        }
}

Потім командний рядок:

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

Переводить висновок команди в Блокнот до тих пір, поки вікно буде відкрито і назване Untitled - Notepad. У випадку, якщо вікно не активне, воно бадьоро буферизується на задньому плані, поки вікно не буде активним. Ви навіть можете перейти до іншої програми, і вона ще раз продовжить буферизацію.

Це, здається, вмирає, коли програма, що виводить на наш стандартний вхід, вмирає, хоча ...

(Для довідки, код stdin () був безсоромно звідси )


...Ого. Якщо ви збираєтеся йти до такої міри, можете також написати цілу складену програму! Можливо, буде і більш ефективним: Хоча піднесіть зусилля.
Боб

Від мене зволікає я. Оверсинінг в класичному розумінні. Хто контролює цей сценарій? Чи потрібна автоматична клавіша для комерційних програм? Хто це стежить?
Гусдор

7
@Gusdor Весь Інтернет наповнений фрагментами коду, що не контролюється версіями. Ми маємо перевагу навіть мати історію редагування цієї публікації. Я також не бачу, як комерційне ліцензування має щось спільне з цим питанням? AHK використовується багатьма людьми, і вони можуть вважати цю відповідь корисною.
slhck

@slhck Я просто зауважував підводні камені цього рішення, а не його обґрунтованість.
Гусдор

@slhck: Вміст на цьому веб-сайті охоплюється Creative Commons.
Брайан

4

Це цілком можливо; Я просто спробував це. Я припускаю, що Блокнот встановлений для відкриття файлів txt за замовчуванням:

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

Гаразд, ви технічно створюєте файл, але він не зберігається.

З'єднання в інші - це також варіант.


4
Будьте обережні - якщо у вас вже є output.txtцей, його буде заглушувати. Дещо безпечніше було б користуватися %temp%/somerandomstring.txt.
Боб

Більш безпечно зберегти вихідний файл у темп-каталозі - погляньте на цю відповідь.
Lu55

1

Ось потворний, але ефективний спосіб досягти цього:

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

Просто не забудьте надіслати лише текстовий вихід. Інші дані потенційно будуть інтерпретуватися як контрольні символи (CTRL, ALT, DEL тощо).


0

Ось пара рішень на основі VBScript, які можуть працювати (хоча .. вони трохи покладаються на відкриття додатків вчасно):

pipe2key.vbs - відкриває додаток, вказаний як перший аргумент, а потім надсилає StdIn як натискання клавіш на нього. Необхідність використання cscript.exe як wscript не забезпечує доступ StdIn. Напевно, досить повільно для довгих документів - але буфер обміну не буде

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

Приклад використання: diff file1.txt file2.txt | cscript pipe2key.vbs notepad.exe

Або, pasteinto.vbs. Автоматизує операцію CTRL-V після запуску програми (таким чином використовується команда 'clip', як зазначено в попередніх відповідях). Значно швидший і чистіший (на мій погляд), ніж pipe2key.vbs, але процес замінить буфер обміну

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"

Приклад використання: diff file1.txt file2.txt | clip && pasteinto notepad.exe


-1

Щось подібне може "спрацювати".

Так, ти не усвідомлював, що це робиш кожен раз вручну (від звуків цього). Можливо, ви зможете зробити якийсь макрос або щось зробити для вас кожного разу, щоб прискорити процес. Не впевнений у цьому.

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

Доведеться закінчити писати вміст diff у file.txt, щоб він міг завантажувати всю дію операції diff, і я не впевнений, чи буде це робити. Можливо, існує спосіб дещо призупинити роботу між трубою, якщо це так.


5
Мета - не створювати тимчасовий файл, і я впевнений, що там щось із вашим синтаксисом не так;)
Der Hochstapler

"для легшого перегляду та редагування пізніше" Я зрозумів, що ви цього хотіли? І як вказував і доповнював Rev1.0, він працює. Це для дос, однак я не впевнений, чи отримав би цигуін ті самі результати.
Codezilla

3
Я здогадуюсь, тому що & & було б адекватним, оскільки насправді нічого не потрібно "прокладати" між цими викликами.
Rev1.0

3
@ Rev1.0 Правильно. &, &&і ||є операторами для об'єднання команд разом. Усі 3 поводяться по-різному в тому, як вони діють, якщо команда генерує значення, яке не повертається 0. |зовсім інший , як вона використовується для труб виходу з однієї програми в іншу. Результат може бути тим, що ви хотіли, але використання одного з ланцюжкових операторів робить наміри зрозумілішими, оскільки в цьому прикладі не потрібні фактичні трубопроводи. Для додаткової довідки: microsoft.com/resources/documentation/windows/xp/all/proddocs/…
Der Hochstapler

1
@Codezilla Я думаю, що ідея в моєму дописі досить схожа на вашу, але це синтаксис командного рядка.
Кейсі

-3

Моя мова не англійська, тому шкода помилок.

Я думаю, що ви не можете безпосередньо поставити вихід у відкритий Блокнот. Можливо, я помиляюся в цьому. Ви повинні створити файл із результатом у ньому, щоб працювати над ним. Команда tee може передавати вихід на два або може бути більше команд або файлів за один і той же час.

людина трійник

Не забудьте використовувати натомість >>, коли ви перемальовуєте вихід у файл. Файл> перезапише файл, >> додасть результат після того, що вже є у цьому файлі.


1
teeзазвичай не доступний в Windows, і навіть якби він був, це не допоможе в цій проблемі.
Der Hochstapler

-4

Ви не можете, Блокнот для цього занадто обмежений! А ще краще ... встановити Cygwin і вирішити все це "відсутність функцій" Windows. Потім можна використовувати команду, яку ви вже знаєте.

AFAIK, дуже небагато програм Windows підтримує конвеєрний рух, що ще гірше для програм GUI.

Ви можете спробувати відкрити запити на функції до однієї з програм «Хвіст вікна», щоб додати це.


2
Я вже використовую cygwin. Це дійсно проблема, специфічна для взаємодії з Notepad.
Der Hochstapler


1
@emodendroket іноді люди використовують неправильний інструмент для роботи ... і майже в будь-якому випадку блокнот - це неправильний інструмент, такий простий і обмежений :)
higuita

1
@higuita Я відданий користувач Emacs, але іноді Блокнот є кращим інструментом для того, що я хочу зробити.
Кейсі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.