Przekierowywanie danych wyjściowych z pliku wsadowego

110

Tworzę plik wsadowy z kilkoma prostymi poleceniami do zbierania informacji z systemu. Plik wsadowy zawiera polecenia, aby uzyskać czas, informacje o adresie IP, użytkowników itp.

Zebrałem wszystkie polecenia w pliku wsadowym i działa, ale chciałbym, aby plik wsadowy po uruchomieniu wyprowadzał wyniki do pliku tekstowego (dziennika). Czy jest polecenie, które mogę dodać do partii, które to zrobi?

Należy pamiętać, że nie chcę uruchamiać partii z cmd, a następnie przekierowywać dane wyjściowe; Chcę przekierować dane wyjściowe z wnętrza wsadu, jeśli to możliwe.

user3085030
źródło

Odpowiedzi:

161

Prosty, naiwny sposób, który jest powolny, ponieważ wielokrotnie otwiera i ustawia wskaźnik pliku na koniec pliku.

@echo off
command1 >output.txt
command2 >>output.txt
...
commandN >>output.txt

Lepszy sposób - łatwiejszy do napisania i szybszy, ponieważ plik jest otwierany i pozycjonowany tylko raz.

@echo off
>output.txt (
  command1
  command2
  ...
  commandN
)

Kolejny dobry i szybki sposób, który otwiera i pozycjonuje plik tylko raz

@echo off
call :sub >output.txt
exit /b

:sub
command1
command2
...
commandN

Edytuj 2020-04-17

Od czasu do czasu możesz chcieć wielokrotnie pisać do dwóch lub więcej plików. Możesz także chcieć wyświetlać różne komunikaty na ekranie. Nadal można to zrobić efektywnie, przekierowując do niezdefiniowanych uchwytów poza blokiem lub podprogramem umieszczonym w nawiasach, a następnie używać &notacji do odwoływania się do już otwartych plików.

call :sub 9>File1.txt 8>File2.txt
exit /b

:sub
echo Screen message 1
>&9 File 1 message 1
>&8 File 2 message 1
echo Screen message 2
>&9 File 1 message 2
>&8 File 2 message 2
exit /b

Zdecydowałem się użyć uchwytów 9 i 8 w odwrotnej kolejności, ponieważ w ten sposób bardziej prawdopodobne jest uniknięcie potencjalnego trwałego przekierowania z powodu błędu projektowego implementacji przekierowania firmy Microsoft podczas wykonywania wielu przekierowań dla tego samego polecenia. Jest to mało prawdopodobne, ale nawet takie podejście może ujawnić błąd, jeśli spróbujesz wystarczająco mocno. Jeśli przygotujesz przekierowanie, na pewno unikniesz problemu.

3>File1.txt ( 4>File2.txt call :sub)
exit /b

:sub
etc.
dbenham
źródło
2
Uwielbiam rozwiązania, w których mogę ustawić to dla pozostałej części pliku
Sam,
3
Zwróć uwagę, że rozwiązanie wywołania zmienia % 0 ( w tym przypadku na sub ), co może, ale nie musi, być tym, czego chcesz.
Jannes
2
@Jannes - prawda, ale zawsze możesz uzyskać informacje o uruchomionym skrypcie wsadowym, jeśli dodasz modyfikator. Na przykład %~f0zawsze podaje pełną ścieżkę do skryptu wsadowego, nawet jeśli znajduje się w podprocedurze CALLed:.
dbenham
3
@ThariqNugrohotomo ->output.txt 2>&1
dbenham
2
@Moondra - jest to standardowa składnia wsadowa do wywoływania podprogramu z etykietą w ramach tego samego skryptu. Wykonaj cmd /?lub help cmdz wiersza poleceń konsoli w celu uzyskania dokumentacji. Sztuczka trzeciej metody polega na tym, że przekierowanie w CALL dotyczy wszystkich poleceń w podprogramie CALLed.
dbenham
66

jeśli chcesz przekierować strumienie out i err

dir >> a.txt 2>&1
Kalpesh Soni
źródło
27
+1. Warto również zwrócić uwagę, że użycie >>doda do a.txt. Aby a.txtzamiast tego nadpisać , użyj >. stackoverflow.com/q/4458231/1098302
Aaron
Cześć, czy jest jakiś sposób na przekierowanie wyjścia również na konsolę?
Sandeep Singh
to właśnie robi
Kalpesh Soni
16

Wiem, że to starszy post, ale ktoś natknie się na niego w wyszukiwarce Google i wygląda na to, że niektóre pytania, które OP zadał w komentarzach, nie zostały szczegółowo omówione. Ponadto, proszę, bądź dla mnie łagodny, ponieważ jest to moja pierwsza odpowiedź opublikowana w SO. :)

Aby przekierować dane wyjściowe do pliku przy użyciu dynamicznie generowanej nazwy pliku, moje podejście do (czytaj: szybkie i brudne) jest drugim rozwiązaniem oferowanym przez @dbenham. Na przykład to:

@echo off
> filename_prefix-%DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log (
echo Your Name Here
echo Beginning Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
REM do some stuff here
echo Your Name Here
echo Ending Date/Time: %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.log
)

Utworzy plik podobny do tego, który widzisz na tym zrzucie ekranu pliku w katalogu docelowym

To będzie zawierać następujące dane wyjściowe:

Your Name Here
Beginning Date/Time: 2016-09-16_141048.log
Your Name Here
Ending Date/Time: 2016-09-16_141048.log

Pamiętaj również, że to rozwiązanie jest zależne od lokalizacji, więc uważaj, jak i kiedy go używasz.

Anthony
źródło
Dzięki temu było to przydatne. Szybkie pytanie, czy istnieje powód, dla którego używasz .log vs .txt? Czy to robi różnicę?
Moondra
1
@Moondra nie, nie ma. W tym przypadku to tylko semantyka. Nie oznacza to, że nie ma aplikacji, które wymagają / grep na podstawie typu pliku, więc po prostu bądź świadomy tego, czy / jak używane są twoje pliki.
Anthony
9
echo some output >"your logfile"

lub

(
 echo some output
 echo more output
)>"Your logfile"

powinien wypełnić rachunek.

Jeśli chcesz uzyskać APPENDdane wyjściowe, użyj >>zamiast >. >uruchomi nowy plik dziennika.

Magoo
źródło
9
@echo off
>output.txt (
echo Checking your system infor, Please wating...

systeminfo | findstr /c:"Host Name" 
systeminfo | findstr /c:"Domain"

ipconfig /all | find "Physical Address" 

ipconfig | find "IPv4" 
ipconfig | find "Default Gateway"

)

@pause
saif
źródło
Myślę, że to najbardziej elegancki sposób. Dzięki Wesley!
Kiswanij
5

Jest fajny mały program, którego możesz użyć do przekierowania wyjścia do pliku i konsoli

some_command  ^|  TEE.BAT  [ -a ]  filename 

AquaAlex
źródło
4

Dodaj te dwie linie w górnej części pliku wsadowego, wszystkie stdout i stderr po zostaną przekierowane do log.txt:

if not "%1"=="STDOUT_TO_FILE"  %0 STDOUT_TO_FILE %*  >log.txt 2>&1
shift /1
ilgitano
źródło
To zadziałało dla mnie, dzięki. Jakieś szczególne względy, które mogą się nie powieść? (np. przepełnienie rozmiaru wyjściowego)
CCarlos
Cześć, dziękuję za odpowiedź! czy jest jakiś sposób na przekierowanie go również na konsolę?
Sandeep Singh
3
@echo OFF
[your command] >> [Your log file name].txt

Użyłem powyższego polecenia w moim pliku wsadowym i działa. W pliku dziennika pokazuje wyniki mojego polecenia.

Indra Permana
źródło
0

Może to się nie powieść w przypadku „toksycznych” znaków na wejściu. Rozważenie takich danych wejściowych, jak this IsAnIn ^^^^, jest dobrym sposobem, aby zrozumieć, co się dzieje. Jasne, że istnieje zasada, że ​​ciąg wejściowy MUSI znajdować się w podwójnych cudzysłowach, ale mam wrażenie, że ta reguła jest prawidłowa tylko wtedy, gdy znaczenie wejścia jest lokalizacją na partycji NTFS (może jest to reguła dla adresów URL I nie jestem pewien). Ale oczywiście nie jest to regułą dla dowolnego ciągu wejściowego (jest to „dobra praktyka”, ale nie można na to liczyć).

jan antonin
źródło
0

Dodanie następujących wierszy u dołu pliku wsadowego spowoduje pobranie wszystkiego tak, jak jest wyświetlane w oknie CMD i wyeksportowanie do pliku tekstowego:

powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^a')
powershell -c "$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('^c')
powershell Get-Clipboard > MyLog.txt

Zasadniczo wykonuje zaznaczenie wszystkiego -> skopiuj do schowka -> wklej do pliku tekstowego .

GioVi
źródło