Zapisywanie danych wyjściowych polecenia w Windows cmd do pliku (z niespodzianką)

9

Próbuję więc uruchomić foo.exe, ale nie chcę, aby dane wyjściowe były wysyłane do terminala, ale do pliku. Bieganie foo.exe > foo.txtpowinno to dla mnie osiągnąć, ale tak nie jest. Kiedy uruchamiam plik exe, otrzymuję wynik. Innymi słowy, exe działa dobrze. Jednak gdy próbuję wysłać dane wyjściowe do pliku, jedyne, co otrzymuję, to:

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

To pojawia się tylko wtedy, gdy próbuję wysłać go do pliku. Myśląc, że może to być c:\Program Files (x86)\źle interpretowana ścieżka (która jest itd.), Próbowałem określić plik wyjściowy w ten sposób: foo.exe > c:\test.txtale nadal nie ma radości.

Więc poza stwierdzeniem, że plik binarny, który próbuję uruchomić, jest źle napisany, czy jest coś, co mogę zrobić, aby temu zaradzić? Pamiętaj, że dostaję prawidłowe dane wyjściowe po prostu po uruchomieniu exe, po prostu nie ładnie wydrukuje do pliku. Oczywiście wynik jest, pytanie brzmi, czy jest jakiś sposób, aby go złapać.

pzkpfw
źródło
Co się stanie, jeśli przeniesiesz program do prostego katalogu (C: \ Simple lub nawet C: \) i wypróbujesz te rzeczy?
Jan Doggen

Odpowiedzi:

22

Nie pokazałeś, że używane polecenie nie działa. Jeśli pokażesz to w swoim pytaniu, może być łatwiej znaleźć dla ciebie rozwiązanie.

Oczekuję, że twoje polecenie jest takie:

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

Błąd, który otrzymujesz, jest nieco wskazówką:

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

Pierwszy:
... is not recognized as an internal or external command, operable program or batch file.

Zwykle dzieje się tak, gdy próbujesz przekierować do pliku za pomocą |zamiast zamiast >.

Druga:
'c:/Program' ...

Określając nazwę pliku (lub ścieżkę), która zawiera spacje, musisz go otoczyć podwójnymi cudzysłowami ( "..."). To dlatego, gdy system operacyjny jest określenie plik do przekierowania, zatrzyma poszukiwaniu pliku po napotkaniu niecytowany miejsca: "c:/Program".

Spróbuj tego:

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



Jeśli powyższe nie działa, aby przechwycić dane wyjściowe foo.exedo pliku tekstowego, istnieje inna możliwość ...

Jeśli program foo.exezapisuje dane wyjściowe STDERRzamiast STDOUT, dane wyjściowe foo.exenie zostaną przechwycone przy użyciu prostego przekierowania z pojedynczym >. Musisz to zrobić w ten sposób:

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



Edytować:

Oto wyjaśnienie przekierowania pliku i 2>&1notacji.

Gdy program zapisuje na terminalu, może pisać do jednego z dwóch Streams.

  1. Strumień 1 jest określany jako STDOUTlub Standard-Output . Zazwyczaj programy zapisują swoje „normalne” dane wyjściowe w strumieniu 1.

  2. Strumień 2 jest określany jako STDERRlub Standard-Error . Zazwyczaj programy zapisują dane wyjściowe „Błąd” (komunikaty o błędach i ostrzeżenia) do strumienia 2.

Czy program zapisuje szczególną wyjście STDOUTalbo STDERRjest określona przez programistę i jak pisali program. Niektóre programy są napisane, aby wysłać wszystkie dane wyjściowe (normalne dane wyjściowe i błędy) do STDOUT.

Gdy program jest uruchamiany bez przekierowania wyjścia, wszystkie normalne i błędne dane wyjściowe są wysyłane do ekranu terminala bez żadnego rozróżnienia między tym, co jest STDOUTwyjściem lub STDERRwyjściem.

Kiedy wykonujesz „normalne” przekierowanie za pomocą jednego >takiego:

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

nie określasz, który strumień jest przekierowywany do pliku, więc zakłada się strumień 1.

To tak, jakbyś wpisał to w ten sposób:

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

Mówi to interpreterowi poleceń ( cmd.exe) o przechwyceniu danych wyjściowych programu STDOUT(Strumień 1) pod określoną nazwę pliku. 1W 1>dotyczy Strumienia 1.

W takim przypadku wszystkie normalne programy są przechwytywane do pliku, ale jeśli program zapisuje w STDERR(Strumień 2), dane wyjściowe nie zostaną przechwycone i zostaną wyświetlone na ekranie. Jest to ogólnie „pożądany” sposób, aby podczas przechwytywania normalnego wyjścia programu można było zobaczyć na ekranie, jeśli wystąpi błąd.

Jeśli chcesz przechwycić wyjście „Normalne” do jednego pliku, a wyjście „Błąd” do innego pliku, możesz to zrobić w następujący sposób:

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

Jeśli chcesz, aby wyjście „Normal” i wyjście „Error” były przechwytywane do tego samego pliku, możesz określić go w następujący sposób:

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

Jest to w zasadzie „skrótowy” sposób określania go i oznacza przekierowanie strumienia 1 do określonego pliku, a także przekierowanie strumienia 2 do tego samego „miejsca” (pliku), co strumień 1.


Edytować:

Pacerier zapytał:

Czy jest jakaś różnica między foo.exe> ​​„c: \ output.txt” 2> & 1 a foo.exe> ​​„c: \ output.txt” 2> „c: \ output.txt”? Czy są identyczne?

Krótka odpowiedź: Można by pomyśleć, że są identyczne, ale nie. Oni są różni.

Przekierowanie z użyciem >"filename.ext", 1>"filename.ext"albo 2>"filename.ext"The >powoduje wyjście być zapisywane w nowym pliku o nazwie „nazwa_pliku.ext”. Jeśli plik „filename.ext” już istnieje, zostanie najpierw usunięty.

Tak więc używając:

foo.exe> ​​„c: \ output.txt” 2> „c: \ output.txt”

powoduje „konflikt”, w którym oba przekierowania próbują zapisać do tego samego pliku i oba próbują usunąć plik, jeśli już istnieje. Spowoduje to prawdopodobnie niepożądane zachowanie. Zasadniczo, jedno lub drugie, lub oba, wyjścia NIE zostaną przechwycone w pełni lub przewidywalnie.

Rzeczywisty wynik zależy od systemu operacyjnego i wersji, a także może zależeć od wykonywanego polecenia. To, co prawdopodobnie się wydarzy, to:

1 Dane wyjściowe wysłane do jednego z przekierowań zostaną przechwycone lub częściowo przechwycone, a dane wyjściowe wysłane do innego przekierowania zostaną utracone. 2 System operacyjny będzie narzekał na polecenie i żadne z wyjść nie zostanie przechwycone (w pełni). 3 Niezdefiniowane, niepożądane, nieprzewidywalne, nieoczekiwane zachowanie.

W systemie Windows 7 i prawdopodobnie w systemie Windows Vista / 8/10 i prawdopodobnie w systemie Windows XP system operacyjny będzie narzekał na polecenie, a polecenie zostanie anulowane.

Na przykład (Windows 7): Mam folder o nazwie: "C:\Temp\emptyfolder"i plik o nazwie „nieistniejący plik” tam nie istnieje.

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>

W tym przypadku, przy użyciu jednego przekierowania ( >output.txt), wyjście dirpolecenia przechwytuje plik output.txt:, a komunikat błędu File Not Foundjest wyświetlany na ekranie ... jest to oczekiwane zachowanie.

Teraz, używając obu przekierowań („> plik” ORAZ „2> plik”):

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>

W takim przypadku system operacyjny skarżył się, że plik (outout) jest już w użyciu. Plik „output.txt” kończy się pusty (0 bajtów), a dane wyjściowe dla obu przekierowań zostały utracone.

Wreszcie, używając obu przekierowań („> plik” ORAZ „2> i 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>

W tym przypadku „> plik” powoduje, że dane wyjściowe dla „strumienia 1” („standardowe wyjście”) są przechwytywane do pliku. A „2> i 1” powoduje, że dane wyjściowe dla „strumienia 2” („wyjście błędu”) są wysyłane przez już przekierowany „strumień 1”, a także przechwytywane do (tego samego) pliku.

Warto również zauważyć, że kolejność jest ważna. Odwracanie kolejności w następujący sposób:

dir nonexistant 2>&1 >output.txt

to nie to samo i prawdopodobnie nie da pożądanego rezultatu.

W tym przypadku „2> i 1”, które są najpierw widoczne i poprzedzone, powodują przekierowanie wyjścia dla „strumienia 2” („wyjście błędu”) do miejsca, do którego obecnie kierowany jest „strumień 1”, na który moment, to (domyślnie) ekran. A „> plik” powoduje, że dane wyjściowe dla „strumienia 1” („standardowe wyjście”) są przechwytywane do pliku. Rezultatem końcowym jest to, że wyjście polecenia („strumień 1”) zostanie przechwycone do pliku, ale wyjście błędu („strumień 2”), nadal przejdzie na ekran (nie do pliku).

Kevin Fegan
źródło
Okazuje się, że foo.exe>"c:\test.txt"tak naprawdę działało, ale zwróciło błąd, że program się zawiesił (choć wyjście nadal tam było). Jednak twoja sugestia uczyniła to jeszcze lepszym, ponieważ 2>&1skarga awarii zniknęła. Chcesz opracować, co robi? Jeszcze raz dziękuję za świetną odpowiedź.
pzkpfw
@ bigbadonk420 - Zaktualizowałem swoją odpowiedź, aby zawierała informacje na temat korzystania z 2>&1. Jeśli sprawdzisz plik „c: \ test.txt”, najprawdopodobniej zauważysz, że do pliku została zapisana „skarga dotycząca awarii” . 2>&1nie powinien powodować lub zapobiegać awariom programu, powoduje jedynie przechwytywanie komunikatów o błędach, a nie ich wyświetlanie.
Kevin Fegan
1
Z jakiegoś powodu tak jest.
pzkpfw
1
@ bigbadonk420 - 'for some reason it does'w jaki sposób wpływa na to przekierowanie? Czy mówisz, że gdy przekierowujesz 2>&1, że błąd nie występuje? Jaki komunikat o błędzie widzisz, gdy wystąpi błąd?
Kevin Fegan
1
Gdy 2>&1nie jest dołączony, program ulega awarii i pojawia się standardowe okno dialogowe „ten program przestał odpowiadać” systemu Windows. Gdy go dołączę, nie będzie. Nie mam pojęcia dlaczego. Dane wyjściowe są generowane w obu przypadkach.
pzkpfw