Làm cách nào để lặp lại và gửi đầu ra giao diện điều khiển đến một tệp trong tập lệnh bat?


136

Tôi có một tập lệnh bó thực thi một tác vụ và gửi đầu ra đến một tệp văn bản. Có cách nào để hiển thị đầu ra trên cửa sổ giao diện điều khiển không?

Ví dụ:

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

Có cách nào để có đầu ra dirhiển thị trong cửa sổ giao diện điều khiển cũng như đặt nó vào tệp văn bản không?


Dưới đây là giải thích về các chuyển hướng bạn có thể thực hiện và một số ví dụ. <br> Hy vọng nó sẽ giúp :)
emoSTN


Xin lưu ý, @Vadzim, rằng một câu hỏi được hỏi vào ngày 2 tháng 2 năm 2009 lúc 16:38 không thể được coi là một bản sao của câu hỏi được hỏi gần ba tháng sau vào ngày 28 tháng 4 năm 2009 lúc 06:32.
Compo

Câu trả lời:


216

Không, bạn không thể chuyển hướng thuần túy.
Nhưng với một số thủ thuật (như tee.bat ) bạn có thể.

Tôi cố gắng giải thích sự chuyển hướng một chút.

Bạn chuyển hướng một trong mười luồng với > tệp hoặc <tệp
Nó không quan trọng, nếu chuyển hướng là trước hoặc sau lệnh, vì vậy hai dòng này gần giống nhau.

dir > file.txt
> file.txt dir

Chuyển hướng trong ví dụ này chỉ là một phím tắt cho 1> , điều này có nghĩa là luồng 1 (STDOUT) sẽ được chuyển hướng.
Vì vậy, bạn có thể chuyển hướng bất kỳ luồng nào bằng cách thêm số như 2> err.txt và nó cũng được phép chuyển hướng nhiều luồng trong một dòng.

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

Trong ví dụ này, "đầu ra tiêu chuẩn" sẽ đi vào files.txt, tất cả các lỗi sẽ ở err.txt và stream3 sẽ chuyển sang nothing.txt (DIR không sử dụng luồng 3).
Stream0 là STDIN
Stream1 là STDOUT
Stream2 là STDERR
Stream3-9 không được sử dụng

Nhưng điều gì xảy ra nếu bạn cố gắng chuyển hướng cùng một luồng nhiều lần?

dir > files.txt > two.txt

"Chỉ có thể có một", và nó luôn luôn là cái cuối cùng!
Vì vậy, nó bằng với dir> hai.txt

Ok, có một khả năng bổ sung, chuyển hướng một luồng sang luồng khác.

dir 1>files.txt 2>&1 

2> & 1 chuyển hướng stream2 sang stream1 và 1> files.txt chuyển hướng tất cả sang files.txt .
Thứ tự là quan trọng ở đây!

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

là khác nhau Dòng đầu tiên chuyển hướng tất cả (STDOUT và STDERR) sang NUL,
nhưng dòng thứ hai chuyển hướng STDOUT sang NUL và STDERR thành STDOUT "trống".

Như một kết luận, rõ ràng là tại sao các ví dụ về Otávio Décio và andynormancx không thể hoạt động.

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

Cả hai đều cố gắng chuyển hướng stream1 hai lần, nhưng "Chỉ có thể có một" và đó luôn là lần cuối cùng.
Vì vậy, bạn nhận được

command 1>&1
dir 1>&2

Và trong mẫu đầu tiên chuyển hướng của stream1 sang stream1 không được phép (và không hữu ích lắm).

Hy vọng nó giúp.


24
Vì vậy, điều này là không thể với shell windows nguyên bản
fantastory

7
@fantastory Có thể, hãy xem giải pháp tuyệt vời này của đợt dbenham Windows: lệnh 'tee'
jeb

97
Tôi không thể tin rằng tôi chỉ đọc toàn bộ bài viết này để tìm hiểu toàn bộ điều có thể được tóm tắt là "Không".
Charles McKelvey

1
Thế còn cơ chế thứ hai "xử lý trùng lặp" thì sao? Tôi đã thử nghiệm 3<&2(lưu ý LT thay vì GT), và sau đó 3>errors.txt. Nhưng điều này đã kết thúc tồi tệ - tất cả đầu ra stderr tiếp theo đã bị bắt errors.txt(nghĩa là - từ các lệnh khác nữa!).
Tomasz Gandor

Bạn có thể sử dụng for /f "delims=" %%v in ('dir') do echo %%v>>file.txtmặc dù.
scriptmastere02

32

Chỉ cần sử dụng phiên bản Windows của lệnh tee UNIX (được tìm thấy từ http://unxutils.sourceforge.net ) theo cách này:

mycommand > tee outpu_file.txt

Nếu bạn cũng cần đầu ra STDERR, thì hãy sử dụng như sau.
Kết 2>&1hợp đầu ra STDERR thành STDOUT (luồng chính).

mycommand 2>&1 | tee output_file.txt

3
Các PowerShell Tee-Object Mời chức năng tương tự. Nhận-Quá trình | Tee-Object -file c: \ scripts \ test.txt
Kevin Obee

Tôi đã thử điều này trong cả powershell và shell thông thường. 1>tee a.txtsẽ chuyển hướng thiết bị xuất chuẩn đến một tệp có tên teethay vì gọi teelệnh. Bất cứ ai có thể xác nhận câu trả lời này làm việc cho họ?
mafu

@mafu Tôi có thể xác nhận điều này.
Cerno

@mafu Câu trả lời ở trên là hơi hợp. Bạn phải sử dụng đường ống "|" thay vì ">" trong ví dụ trên. Thật kỳ lạ, thứ tự của đầu ra STDOUT và STDERR được trộn lẫn trên dòng lệnh trong trường hợp đó. Ví dụ dưới hoạt động hoàn hảo cho tôi mặc dù.
Cerno

Ngoài ra, tải về sourceforge đã bị hỏng đối với tôi. Tôi tìm thấy một máy chủ thay thế ở đây: wzw.tum.de/public-html/syring/win32/UnxUtilsDist.html (Đại học Munich)
Cerno

9

Nếu bạn không cần đầu ra trong thời gian thực (ví dụ như chương trình đang viết nó), bạn có thể thêm

type windows-dir.txt

sau dòng đó.


hoặc trên cùng một dòng (hữu ích tại dấu nhắc) : dir > windows-dir.txt & type windows-dir.txt. Điều này cũng áp dụng cho các khối : ( echo %date% <NL> echo %username% <NL> echo %time% <NL> pause>CON )>test.txt & type test.txt. Tuy nhiên, nếu đầu ra là bắt buộc trong thời gian thực, bạn có thể sử dụng ví dụ: cổng windows của công cụ tee cho điều đó
mousio

7

Giải pháp hiệu quả với tôi là: dir> a.txt | gõ a.txt .


2
Điều này hoạt động với lệnh với đầu ra thấp. Với lệnh đầu ra lớn, nó không hoạt động vì nó chỉ hiển thị bộ đệm đầu tiên. Anh ta yêu cầu một đầu ra thời gian thực trong khi lưu đầu ra vào một tệp nhật ký.
NetVicy

Sẽ có vấn đề nếu bạn sử dụng >> thay vì>
Nime Cloud

6

Có, có một cách để hiển thị một đầu ra lệnh duy nhất trên bàn điều khiển (màn hình) và trong một tệp. Sử dụng ví dụ của bạn, sử dụng ...

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

Giải thích chi tiết:

Các FORlệnh phân tích đầu ra của một lệnh hoặc văn bản vào một biến, mà có thể được tham chiếu nhiều lần.

Đối với một lệnh, chẳng hạn như DIR /B, kèm theo các dấu ngoặc đơn như trong ví dụ dưới đây. Thay thế DIR /Bvăn bản bằng lệnh mong muốn của bạn.

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

Để hiển thị văn bản, hãy đóng văn bản trong dấu ngoặc kép như trong ví dụ dưới đây.

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

... Và với gói hàng ...

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

Nếu bạn có thời gian khi bạn chỉ muốn đầu ra trên bàn điều khiển (màn hình) và những lần khác chỉ được gửi đến tệp và những lần khác được gửi cho cả hai, hãy chỉ định mệnh đề "DO" của vòng lặp FOR bằng cách sử dụng một biến như dưới đây %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

Bạn nên sử dụng delims=thay thế.
scriptmastere02

3
command > file >&1

Sẽ nhanh hơn khi bạn không ghi dữ liệu ra màn hình vì bạn không lấp đầy bộ đệm bằng crap mà thay vào đó cho phép bạn thực hiện công việc hàng loạt. nếu bạn đang gỡ lỗi tôi sẽ không sử dụng cú pháp tệp>.
Nhà phát triển ngẫu nhiên

@andynormancx yup quên gõ thay vì cắt và dán từ CMD.
Nhà phát triển ngẫu nhiên

Tôi không thể có được cú pháp để làm việc theo dấu nhắc lệnh của windows và thay vào đó đã sử dụng lệnh type.
JamesEggers

& 2 không hoạt động tuy nhiên tệp hiện không được tạo khi tôi kiểm tra.
JamesEggers

5
nếu tôi không tạo tệp "dir> file.txt> & 2" thì không được tạo. Đầu ra của thư mục đang được lặp lại trong bảng điều khiển nhưng tệp không được tạo. Tệp được tạo khi không có "> & 2".
JamesEggers

2

Nếu bạn muốn chắp thêm thay vì thay thế tệp đầu ra, bạn có thể muốn sử dụng

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

hoặc là

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

2

Lựa chọn của tôi là thế này:

Tạo một chương trình con nhận thông báo và tự động hóa quá trình gửi nó đến cả bảng điều khiển và tệp nhật ký.

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

Nếu bạn thêm một biến vào tin nhắn, hãy chắc chắn xóa các dấu ngoặc kép trong nó trước khi gửi nó đến chương trình con hoặc nó có thể làm hỏng lô của bạn. Tất nhiên điều này chỉ hoạt động cho tiếng vang.


Ôi CÓ! Tôi thực sự thích điều này !! Tôi đã thực hiện ba thay đổi, tôi hy vọng bạn thích chúng. 1) Tôi sử dụng setlocal enabledelayedexpansionthay vì chỉ setlocal 2) Tôi sử dụng mở rộng bị trì hoãn cho biến logfile, vì vậy >> !logfile!thay vì >> %logfile%trong chương trình con. Theo cách này, nó hoạt động khi được gọi từ trong một khối mã (như trong câu lệnh if). 3) Tôi đã xóa dòng "set message" vì không cần thêm biến. Chúng tôi đã có nó trong $~1vì vậy tôi có echo $~1cho cả hai lệnh echo.
Nate

2

Tôi đã tạo một bảng điều khiển C # đơn giản có thể xử lý đầu ra thời gian thực cho cả màn hình cmd và nhật ký

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;
    }
}

Việc sử dụng tệp bó giống như cách bạn sử dụng Unix tee

foo | tee xxx.log

Và đây là kho lưu trữ bao gồm Tee.exe trong trường hợp bạn không có công cụ để biên dịch https://github.com/iamshiao/Tee


1

Tôi thích câu trả lời của atn, nhưng nó không tầm thường đối với tôi để tải xuống dưới dạng wintee , đây cũng là nguồn mở và chỉ cung cấp chức năng tee (hữu ích nếu bạn chỉ muốn tee chứ không phải toàn bộ các tiện ích unix). Tôi đã học được điều này từ câu trả lời của davor đến Hiển thị đầu ra dấu nhắc lệnh Windows và chuyển hướng nó đến một tệp , nơi bạn cũng tìm thấy tài liệu tham khảo cho các tiện ích unix.


0

Giải pháp được cung cấp bởi "Tomas R" hoạt động hoàn hảo cho câu hỏi của OP và nó thực sự có sẵn.

Hãy thử: chkdsk c:> output.txt | gõ output.txt

Đầu ra của lệnh này liên quan đến một tỷ lệ phần trăm hoàn thành có được đầu ra serent cho tệp do đó nó sẽ trông hơi lộn xộn (tức là văn bản sẽ được thêm vào khi nó tiến triển). Điều này không xảy ra với các bit được xuất ra STDOUT (màn hình). Đó là cách nó sẽ xảy ra nếu bạn chỉ thực hiện cùng một lệnh mà không chuyển hướng.


-3

Tôi nghĩ rằng bạn muốn một cái gì đó dọc theo dòng này:

echo Your Msg> YourTxtFile.txt

Hoặc nếu bạn muốn một dòng mới:

echo Your Msg>> YourTxtFile.txt

Các lệnh này là tuyệt vời cho các bản ghi.

Lưu ý: Điều này đôi khi sẽ trục trặc và thay thế toàn bộ tệp văn bản trên máy tính của tôi.

Lưu ý khác: Nếu tệp không tồn tại, nó sẽ tạo tệp.


1
không, OP muốn có đầu ra thành một tệp trên màn hình. Bạn chỉ cần viết vào tập tin. (Và >được thiết kế để ghi đè lên tệp. Sử dụng >>để chắp thêm )
Stephan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.