Bagaimana cara saya echo dan mengirim output konsol ke file dalam skrip bat?


140

Saya memiliki skrip batch yang menjalankan tugas dan mengirimkan hasilnya ke file teks. Apakah ada cara untuk menampilkan output di jendela konsol juga?

Sebagai contoh:

c:\Windows>dir > windows-dir.txt

Apakah ada cara untuk memiliki keluaran dirtampilan di jendela konsol serta memasukkannya ke dalam file teks?


Berikut adalah penjelasan pengalihan yang dapat Anda lakukan, dan beberapa contoh. <br> Semoga membantu :)
emoSTN


Harap dicatat, @Vadzim, bahwa pertanyaan yang diajukan pada 2 Feb 2009 pada 16:38 tidak dapat dianggap sebagai duplikat dari pertanyaan yang diajukan hampir tiga bulan kemudian pada 28 Apr 2009 pada 06:32.
Kompo

Jawaban:


219

Tidak, Anda tidak bisa dengan pengalihan murni.
Tetapi dengan beberapa trik (seperti tee.bat ) Anda bisa.

Saya mencoba menjelaskan pengalihan sedikit.

Anda mengarahkan salah satu dari sepuluh aliran dengan > file atau <file
Itu tidak penting, jika pengalihan sebelum atau sesudah perintah, jadi kedua baris ini hampir sama.

dir > file.txt
> file.txt dir

Pengalihan dalam contoh ini hanya pintasan untuk 1> , ini berarti aliran 1 (STDOUT) akan dialihkan.
Jadi Anda dapat mengarahkan aliran apa pun dengan nomor sebelumnya seperti 2> err.txt dan juga diperbolehkan untuk mengarahkan beberapa aliran dalam satu baris.

dir 1> files.txt 2> err.txt 3> nothing.txt

Dalam contoh ini, "keluaran standar" akan masuk ke files.txt, semua kesalahan akan ada di err.txt dan stream3 akan masuk ke nothing.txt (DIR tidak menggunakan aliran 3).
Stream0 adalah STDIN
Stream1 adalah STDOUT
Stream2 adalah STDERR
Stream3-9 tidak digunakan

Tetapi apa yang terjadi jika Anda mencoba mengalihkan aliran yang sama beberapa kali?

dir > files.txt > two.txt

"Hanya ada satu", dan itu selalu yang terakhir!
Jadi sama dengan dir> two.txt

Oke, ada satu kemungkinan tambahan, mengalihkan aliran ke aliran lain.

dir 1>files.txt 2>&1 

2> & 1 mengalihkan aliran2 ke aliran1 dan 1> files.txt mengarahkan semua ke files.txt .
Urutan penting di sini!

dir ... 1>nul 2>&1
dir ... 2>&1 1>nul

berbeda. Yang pertama mengalihkan semua (STDOUT dan STDERR) ke NUL,
tetapi baris kedua mengalihkan STDOUT ke NUL dan STDERR ke STDOUT "kosong".

Sebagai satu kesimpulan, jelas mengapa contoh Otávio Décio dan andynormancx tidak dapat bekerja.

command > file >&1
dir > file.txt >&2

Keduanya mencoba mengalihkan aliran1 dua kali, tetapi "Hanya ada satu", dan itu selalu yang terakhir.
Jadi Anda mengerti

command 1>&1
dir 1>&2

Dan pada contoh pertama, pengalihan stream1 ke stream1 tidak diperbolehkan (dan tidak terlalu berguna).

Semoga membantu.


24
Jadi tidak mungkin dengan windows shell asli
fantastory

7
@fantastory Mungkin saja, lihat solusi hebat dbenham Windows batch: perintah 'tee'
jeb

100
Saya tidak percaya saya baru saja membaca keseluruhan posting ini untuk mengetahui semuanya dapat diringkas sebagai "Tidak".
Charles McKelvey

1
Bagaimana dengan mekanisme kedua "menangani duplikasi"? Saya bereksperimen dengan 3<&2(perhatikan LT, bukan GT), dan kemudian 3>errors.txt. Tetapi ini berakhir dengan buruk - semua output stderr berikutnya ditangkap ke errors.txt(yaitu - dari perintah lain juga!).
Tomasz Gandor

1
@CharlesMcKelvey (dan semua upvoters) apakah Anda akan menerima jawaban yang hanya mengatakan "Tidak"? Atau apakah Anda lebih suka penjelasan?
Rodrigo.A92

33

Cukup gunakan versi Windows dari perintah tee UNIX (ditemukan dari http://unxutils.sourceforge.net ) dengan cara ini:

mycommand > tee outpu_file.txt

Jika Anda juga membutuhkan keluaran STDERR, gunakan yang berikut ini.
The 2>&1menggabungkan output stderr ke STDOUT (streaming utama).

mycommand 2>&1 | tee output_file.txt

3
The PowerShell Tee-Obyek penawaran fungsi serupa. Dapatkan-Proses | Tee-Object -file c: \ scripts \ test.txt
Kevin Obee

Saya mencoba ini di PowerShell dan shell biasa. 1>tee a.txtakan mengarahkan stdout ke file bernama teealih-alih memanggil teeperintah. Adakah yang bisa memastikan bahwa jawaban ini berhasil untuk mereka?
mafu

@mafu Saya dapat mengkonfirmasi ini.
Cerno

@mafu Jawaban di atas sedikit salah. Anda harus menggunakan pipa "|" bukannya ">" di contoh atas. Anehnya, urutan keluaran STDOUT dan STDERR tercampur pada baris perintah dalam kasus tersebut. Contoh bawah bekerja dengan sempurna untuk saya.
Cerno

Juga, unduhan sourceforge rusak untuk saya. Saya menemukan tuan rumah alternatif di sini: wzw.tum.de/public-html/syring/win32/UnxUtilsDist.html (Universitas Munich)
Cerno

9

Jika Anda tidak memerlukan output secara real time (misalnya saat program menulisnya), Anda dapat menambahkan

type windows-dir.txt

setelah garis itu.


atau pada baris yang sama (berguna pada prompt): dir > windows-dir.txt & type windows-dir.txt. Ini juga berlaku untuk blok: ( echo %date% <NL> echo %username% <NL> echo %time% <NL> pause>CON )>test.txt & type test.txt. Namun, jika output diperlukan secara real time, Anda dapat menggunakan misalnya port windows alat tee untuk itu…
mousio

7

Solusi yang berhasil untuk saya adalah: dir> a.txt | ketik a.txt .


2
Ini bekerja dengan perintah dengan output rendah. Dengan perintah keluaran besar itu tidak berfungsi karena hanya menampilkan buffer pertama. Dia itu meminta keluaran waktu nyata sambil menyimpan keluaran ke file log.
NetVicious

Akan bermasalah jika Anda menggunakan >> alih-alih>
Nime Cloud

6

Ya, ada cara untuk menampilkan satu output perintah di konsol (layar) dan di file. Menggunakan contoh Anda, gunakan ...

@ECHO OFF
FOR /F "tokens=*" %%I IN ('DIR') DO ECHO %%I & ECHO %%I>>windows-dir.txt

Penjelasan detail:

Itu FOR perintah mem-parsing output dari perintah atau teks ke dalam variabel, yang dapat dirujuk beberapa kali.

Untuk perintah, seperti DIR /B, apit dalam tanda kutip tunggal seperti yang ditunjukkan pada contoh di bawah ini. Ganti DIR /Bteks dengan perintah yang Anda inginkan.

FOR /F "tokens=*" %%I IN ('DIR /B') DO ECHO %%I & ECHO %%I>>FILE.TXT

Untuk menampilkan teks, apit teks dalam tanda kutip ganda seperti yang ditunjukkan pada contoh di bawah ini.

FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO ECHO %%I & ECHO %%I>>FILE.TXT

... Dan dengan pembungkus garis ...

FOR /F "tokens=*" %%I IN ("Find this text on console (screen) and in file") DO (
  ECHO %%I & ECHO %%I>>FILE.TXT
)

Jika Anda memiliki waktu di mana Anda ingin output hanya di konsol (layar), dan waktu lain hanya dikirim ke file, dan waktu lain dikirim ke keduanya, tentukan klausa "DO" dari loop FOR menggunakan variabel, seperti yang ditunjukkan di bawah ini dengan %TOECHOWHERE%.

@ECHO OFF
FOR %%I IN (TRUE FALSE) DO (
  FOR %%J IN (TRUE FALSE) DO (
    SET TOSCREEN=%%I & SET TOFILE=%%J & CALL :Runit)
)
GOTO :Finish

:Runit
  REM Both TOSCREEN and TOFILE get assigned a trailing space in the FOR loops
  REM above when the FOR loops are evaluating the first item in the list,
  REM "TRUE".  So, the first value of TOSCREEN is "TRUE " (with a trailing
  REM space), the second value is "FALSE" (no trailing or leading space).
  REM Adding the ": =" text after "TOSCREEN" tells the command processor to
  REM remove all spaces from the value in the "TOSCREEN" variable.
  IF "%TOSCREEN: =%"=="TRUE" (
      IF "%TOFILE: =%"=="TRUE" (
          SET TEXT=On screen, and in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I & ECHO %%I>>FILE.TXT"
        ) ELSE (
          SET TEXT=On screen, not in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I"
      )
    ) ELSE (
      IF "%TOFILE: =%"=="TRUE" (
          SET TEXT=Not on screen, but in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I>>FILE.txt"
        ) ELSE (
          SET TEXT=Not on screen, nor in "FILE.TXT"
          SET TOECHOWHERE="ECHO %%I>NUL"
      )
  )
  FOR /F "tokens=*" %%I IN ("%TEXT%") DO %TOECHOWHERE:~1,-1%
GOTO :eof

:Finish
  ECHO Finished [this text to console (screen) only].
  PAUSE

Anda harus menggunakan delims=sebagai gantinya.
scriptmastere02

3
command > file >&1

Ini lebih cepat ketika Anda tidak menulis data ke layar karena Anda tidak mengisi buffer dengan omong kosong melainkan membiarkan Anda menjalankan pekerjaan batch. jika Anda debugging saya tidak akan menggunakan> file sintaks.
Pengembang Acak

@andynormancx yup lupa mengetiknya alih-alih potong dan tempel dari CMD.
Pengembang Acak

Saya tidak bisa mendapatkan sintaks untuk bekerja di bawah prompt perintah windows dan telah menggunakan perintah type sebagai gantinya.
JamesEggers

& 2 berfungsi, namun file tidak sedang dibuat saat saya mengujinya.
JamesEggers

5
jika saya melakukan "dir> file.txt> & 2" file.txt tidak sedang dibuat. Output dari direktori sedang di-echo di konsol tetapi file tidak sedang dibuat. File dibuat jika "> & 2" tidak ada.
JamesEggers

2

Jika Anda ingin menambahkan alih-alih mengganti file keluaran, Anda mungkin ingin menggunakan

dir 1>> files.txt 2>> err.txt

atau

dir 1>> files.txt 2>>&1

2

Pilihan saya adalah ini:

Buat subrutin yang menerima pesan dan mengotomatiskan proses pengirimannya ke konsol dan file log.

setlocal
set logfile=logfile.log

call :screenandlog "%DATE% %TIME% This message goes to the screen and to the log"    

goto :eof

:screenandlog
set message=%~1
echo %message% & echo %message% >> %logfile%
exit /b

Jika Anda menambahkan variabel ke pesan, pastikan untuk menghapus tanda kutip di dalamnya sebelum mengirimkannya ke subrutin atau dapat mengacaukan batch Anda. Tentu saja ini hanya berfungsi untuk gema.


WOW YA! Saya sangat menyukai ini!! Saya membuat tiga perubahan, saya harap Anda menyukainya. 1) Saya menggunakan setlocal enabledelayedexpansionbukan hanya setlocal 2) Saya menggunakan ekspansi tertunda untuk variabel logfile, jadi >> !logfile!alih-alih >> %logfile%dalam subrutin. Dengan cara ini, ini berfungsi ketika dipanggil dari dalam blok kode (seperti dalam pernyataan if). 3) Saya menghapus baris "set message" karena tidak perlu variabel tambahan. Kami sudah memilikinya $~1jadi saya punya echo $~1untuk kedua perintah gema.
Nate

2

Saya membuat konsol C # sederhana yang dapat menangani output real-time ke layar cmd dan log

class Tee
{
    static int Main(string[] args)
    {
        try
        {
            string logFilePath = Path.GetFullPath(args[0]);

            using (StreamWriter writer = new StreamWriter(logFilePath, true))
            {
                for (int value; (value = Console.In.Read()) != -1;)
                {
                    var word = Char.ConvertFromUtf32(value);
                    Console.Write(word);
                    writer.Write(word);
                }
            }
        }
        catch (Exception)
        {
            return 1;
        }
        return 0;
    }
}

Penggunaan file batch sama dengan cara Anda menggunakan Unix tee

foo | tee xxx.log

Dan inilah repositori yang menyertakan Tee.exe jika Anda tidak memiliki alat untuk mengompilasi https://github.com/iamshiao/Tee



0

Solusi yang disediakan oleh "Tomas R" bekerja sempurna untuk pertanyaan OP dan tersedia secara native.

Coba: chkdsk c:> output.txt | ketik output.txt

Output dari perintah ini melibatkan persentase penyelesaian yang mendapatkan output secara serial ke file sehingga akan terlihat agak berantakan (yaitu teks akan ditambahkan saat proses berlangsung). Ini tidak terjadi pada bit yang mendapatkan output ke STDOUT (layar). Begitulah jadinya jika Anda hanya melakukan perintah yang sama tanpa pengalihan.


-3

Saya pikir Anda menginginkan sesuatu seperti ini:

echo Your Msg> YourTxtFile.txt

Atau jika Anda menginginkan baris baru:

echo Your Msg>> YourTxtFile.txt

Perintah ini bagus untuk log.

Catatan: Ini terkadang kesalahan dan mengganti seluruh file teks di komputer saya.

Catatan Lain: Jika file tidak ada, itu akan membuat file.


1
tidak, OP ingin memiliki output ke dalam file dan di layar. Anda baru saja menulis ke file. (Dan >ini dirancang untuk menimpa file Gunakan. >>Untuk menambahkan )
Stephan
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.