Запись вывода команды в Windows cmd в файл (с изюминкой)

9

Итак, я пытаюсь запустить foo.exe, но я не хочу вывод на терминал, но в файл. Бег foo.exe > foo.txtдолжен сделать это для меня, но это не так. Когда я запускаю exe-файл, я получаю вывод. Exe работает нормально, другими словами. Однако, когда я пытаюсь отправить вывод в файл, единственное, что я получаю, это:

'c:/Program' is not recognized as an internal or external command,
operable program or batch file.

Это появляется только когда я пытаюсь отправить его в файл. Думая, что это может быть путь (который c:\Program Files (x86)\и так далее), который неверно истолкован, я попытался указать выходной файл следующим образом:, foo.exe > c:\test.txtно все равно не радость.

Итак, помимо заявления о том, что бинарный файл, который я пытаюсь запустить, написан плохо, могу ли я что-нибудь сделать, чтобы исправить это? Имейте в виду, что я получаю корректный вывод при простом запуске exe, он просто не будет хорошо печататься в файл. Очевидно, что выход есть, вопрос в том, есть ли какой-нибудь способ его поймать.

PzKpfw
источник
Что произойдет, если вы переместите программу в простой каталог (C: \ Simple или даже C: \) и попробуете оттуда?
Ян Догген

Ответы:

21

Вы не показали, что команда, которую вы используете, не работает. Если вы показываете это в своем вопросе, может быть, будет проще найти решение для вас.

Я ожидаю, что ваша команда примерно такая:

C:\>foo.exe|c:\Program Files (x86)\something\test.txt

Ошибка, которую вы получаете, является своего рода подсказкой:

'c:/Program' is not recognized as an internal or external command, operable program or batch file.

Первый:
... is not recognized as an internal or external command, operable program or batch file.

Обычно это происходит, когда вы пытаетесь перенаправить в файл, используя |вместо >.

Во-вторых:
'c:/Program' ...

При указании имени файла (или пути), содержащего пробелы, вы должны заключить его в двойные кавычки ( "..."). Это происходит потому , что когда ОС является определение файла для перенаправления, он будет не искать имя файла , когда он встречает в кавычках пространства: "c:/Program".

Попробуй это:

foo.exe>"c:\Program Files (x86)\something\test.txt"



Если вышеупомянутое не работает, чтобы захватить вывод из foo.exeв текстовый файл, то есть другая возможность ...

Если программа foo.exeзаписывает свой вывод STDERRвместо STDOUT, вывод foo.exeне будет получен с помощью простого перенаправления с одним >. Вы должны сделать это так:

foo.exe>"c:\Program Files (x86)\something\test.txt" 2>&1



Редактировать:

Вот объяснение перенаправления файла и 2>&1обозначения.

Когда программа пишет в терминал, она может писать в одну из двух Streams.

  1. Поток 1 называется STDOUTили стандартным выходом . Обычно программы записывают свой «нормальный» вывод в поток 1.

  2. Поток 2 называется STDERRили Standard-Error . Обычно программы записывают свои выходные данные «Error» (сообщения об ошибках и предупреждения) в поток 2.

Записывает ли программа определенный вывод STDOUTили STDERRопределяет программист и как они написали программу. Некоторые программы написаны для отправки всего вывода (нормального вывода и ошибок) STDOUT.

Когда программа запускается без перенаправления вывода, все нормальные и ошибочные выходные данные отправляются на экран терминала без какого-либо различия между STDOUTвыходными или STDERRвыходными данными.

Когда вы делаете «нормальное» перенаправление с одним, >как это:

foo.exe > "c:\Program Files (x86)\something\test.txt"

Вы не указываете, какой поток перенаправляется в файл, поэтому предполагается, что поток 1.

Это так же, как если бы вы напечатали это так:

foo.exe 1> "c:\Program Files (x86)\something\test.txt"

Это говорит интерпретатору команды ( cmd.exe) захватить вывод программы для STDOUT(Поток 1) с указанным именем файла. 1В 1>относится к потоку 1.

В этом случае вся обычная программа записывается в файл, но если программа записывает в STDERR(Поток 2), этот вывод не будет записан и будет показан на экране. Как правило, это «желаемый» способ сделать это так, чтобы во время захвата нормального вывода программы вы могли видеть на экране, если происходит ошибка.

Если вы хотите записать вывод «Normal» в один файл, а вывод «Error» в другой файл, вы можете сделать это следующим образом:

    foo.exe > "c:\output.txt" 2> "C:\error.txt"
or
    foo.exe 1> "c:\output.txt" 2> "C:\error.txt"

Если вы хотите, чтобы вывод «Normal» и вывод «Error» были записаны в один и тот же файл, вы можете указать его следующим образом:

foo.exe > "c:\output.txt" 2>&1

По сути, это «сокращенный» способ его указания, и он означает перенаправление потока 1 в указанный файл, а также перенаправление потока 2 в то же «место» (файл), что и поток 1.


Редактировать:

Пейсер спросил:

Есть ли разница между foo.exe> ​​"c: \ output.txt" 2> & 1 и foo.exe> ​​"c: \ output.txt" 2> "c: \ output.txt"? Они идентичны?

Краткий ответ: Вы могли бы подумать, что они идентичны, но нет. Они разные.

При перенаправлении с использованием >"filename.ext", 1>"filename.ext"или 2>"filename.ext", >выходные данные записываются в новый файл с именем «filename.ext». Если файл «filename.ext» уже существует, он будет удален первым.

Итак, используя:

foo.exe> ​​"c: \ output.txt" 2> "c: \ output.txt"

вызывает «конфликт», когда оба перенаправления пытаются записать в один и тот же файл, и оба пытаются удалить файл, если он уже существует. Это может вызвать нежелательное поведение. Как правило, один или другой или оба выходных сигнала НЕ будут захвачены полностью или предсказуемо.

Фактический результат будет зависеть от операционной системы и версии, а также может зависеть от выполняемой команды. Что, скорее всего, произойдет:

1 Выход, отправленный на одно из перенаправлений, будет захвачен или частично захвачен, а выход, отправленный на другое перенаправление, будет потерян. 2 Операционная система будет жаловаться на команду, и ни один из выходов не будет зафиксирован (полностью). 3 Неопределенное, нежелательное, непредсказуемое, неожиданное поведение.

В Windows 7 и, вероятно, в Windows Vista / 8/10 и, возможно, в Windows XP, операционная система будет жаловаться на команду, и команда будет отменена.

Например (Windows 7): у меня есть папка с именем: "C:\Temp\emptyfolder"и файл с именем "nonexistantfile" там не существует.

C:\>cd "\Temp\emptyfolder"

C:\Temp\emptyfolder>dir nonexistantfile>output.txt
File Not Found

C:\Temp\emptyfolder>type output.txt
 Volume in drive F is FFFFx1tb
 Volume Serial Number is 4011-A5C6

 Directory of C:\Temp\emptyfolder

C:\Temp\emptyfolder>

В этом случае, используя одну функцию redirection ( >output.txt), вывод dirкоманды записывается в файл:, output.txtи сообщение об ошибке File Not Foundотображается на экране ... это ожидаемое поведение.

Теперь, используя оба перенаправления («> файл» И «2> файл»):

C:\Temp\emptyfolder>dir nonexistantfile>output.txt 2>output.txt
The process cannot access the file because it is being used by another process.
C:\Temp\emptyfolder>type output.txt

C:\Temp\emptyfolder>

В этом случае операционная система жаловалась, что (выходной) файл уже используется. И файл «output.txt» заканчивается пустым (0 байт), и выходные данные для обоих перенаправлений были потеряны.

Теперь, наконец, используя оба перенаправления ("> файл" И "2> & 1"):

C:\Temp\emptyfolder>dir nonexistantfile>output.txt 2>&1

C:\Temp\emptyfolder>type output.txt
 Volume in drive C is CCCCCCCC
 Volume Serial Number is 1234-ABCD

 Directory of C:\Temp\emptyfolder

File Not Found

C:\Temp\emptyfolder>

В этом случае «> файл» приводит к тому, что вывод для «потока 1» («стандартный вывод») записывается в файл. И «2> & 1» заставляет вывод для «потока 2» («вывод ошибки») через уже перенаправленный «поток 1», а также записывается в (тот же) файл.

Также стоит отметить, что порядок важен. В обратном порядке, как это:

dir nonexistant 2>&1 >output.txt

не то же самое и, вероятно, не даст вам желаемого результата.

В этом случае «2> & 1», который просматривается и обрабатывается первым, приводит к тому, что вывод «потока 2» («вывод ошибки») перенаправляется в то место, куда в данный момент направлен «поток 1», что при этом моментом является (по умолчанию) экран. И "> файл" заставляет вывод для "потока 1" ("стандартный вывод") быть записанным в файл. Конечным результатом является то, что вывод команды («поток 1») будет записан в файл, но вывод ошибок («поток 2») все равно будет отображаться на экране (а не в файле).

Кевин Феган
источник
Оказалось, что это foo.exe>"c:\test.txt"действительно сработало, но выдало ошибку из-за сбоя программы (хотя вывод все еще был). Тем не менее, ваше предложение сделало его еще лучше, поскольку 2>&1жалоба на аварию прошла. Хотите уточнить, что он делает? Еще раз спасибо за отличный ответ.
pzkpfw
@ bigbadonk420 - я обновил свой ответ, включив в него информацию об использовании 2>&1. Если вы изучите свой файл «c: \ test.txt», вы, скорее всего, увидите, что в него была записана «жалоба на сбой» . 2>&1не должен вызывать или предотвращать сбой программы, он просто вызывает, а не отображает сообщения об ошибках.
Кевин Феган
1
Ну, по некоторым причинам это так.
pzkpfw
1
@ bigbadonk420 - 'for some reason it does'как на него влияет перенаправление? Вы говорите, что при перенаправлении, в том числе 2>&1, что ошибка не возникает? Какое сообщение об ошибке вы видите при возникновении ошибки?
Кевин Феган
1
Когда 2>&1не включен, программа вылетает, и я получаю стандартный Windows-диалог «эта программа перестала отвечать». Когда я включаю это, это не так. Понятия не имею почему. Вывод генерируется в обоих случаях, хотя.
pzkpfw