Bir yarasa betiğindeki bir dosyaya konsol çıktısını nasıl yankılayıp gönderebilirim?


136

Bir görevi yürütür ve çıktı bir metin dosyasına gönderir bir toplu iş komut dosyası var. Konsol penceresinde çıktının gösterilmesinin bir yolu var mı?

Örneğin:

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

dirKonsol penceresinde görüntü çıktısı almanın ve metin dosyasına koymanın bir yolu var mı?


Burada yapabileceğiniz yönlendirmeler ve bazı örnekler açıklanmıştır. <br> Umarım yardımcı olur :)
emoSTN


@Vadzim, 2 Şubat 2009 saat 16:38'de sorulan bir sorunun, neredeyse üç ay sonra 28 Nisan 2009 saat 06:32'de sorulan bir sorunun kopyası olarak değerlendirilemeyeceğini unutmayın.
Compo

Yanıtlar:


216

Hayır, saf yönlendirme ile yapamazsınız.
Ama bazı hilelerle ( tee.bat gibi ) yapabilirsiniz.

Yönlendirmeyi biraz açıklamaya çalışıyorum.

On akıştan birini > dosya veya <dosya ile yeniden yönlendirirsiniz. Yeniden yönlendirme
komuttan önce veya sonraysa, önemsizdir, bu nedenle bu iki satır hemen hemen aynıdır.

dir > file.txt
> file.txt dir

Bu örnekteki yönlendirme yalnızca 1> için bir kısayoldur , yani akış 1 (STDOUT) yeniden yönlendirilecektir.
Böylece herhangi bir akışı 2> err.txt gibi bir sayı ekleyerek yeniden yönlendirebilirsiniz ve ayrıca bir satırda birden fazla akışı yeniden yönlendirmesine izin verilir.

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

Bu örnekte "standart çıktı" files.txt dosyasına, tüm hatalar err.txt dosyasında ve stream3 hiçbir şey.txt dosyasında olacaktır (DIR, akış 3'ü kullanmaz).
Stream0 is STDIN
Stream1 is STDOUT
Stream2 is STDERR
Stream3-9 kullanılmıyor

Ancak aynı akışı birden çok kez yönlendirmeye çalışırsanız ne olur?

dir > files.txt > two.txt

"Sadece bir tane olabilir" ve her zaman sonuncusu!
Yani dir> two.txt 'e eşittir

Tamam, bir akışı başka bir akışa yönlendiren fazladan bir olasılık var.

dir 1>files.txt 2>&1 

2> ve 1 yönlendirme stream2 için Stream1 ve 1> files.txt yönlendirmeler tüm files.txt .
Burada sipariş önemlidir!

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

farklıdır. Birincisi tümünü (STDOUT ve STDERR) NUL'a yönlendirir,
ancak ikinci satır STDOUT'u NUL'a ve STDERR'ı "boş" STDOUT'a yönlendirir.

Bir sonuç olarak, Otávio Décio ve andynormancx örneklerinin neden çalışamayacağı açıktır.

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

Her ikisi de stream1'i iki kez yönlendirmeye çalışır, ancak "Yalnızca bir tane olabilir" ve her zaman sonuncusudur.
Yani sen al

command 1>&1
dir 1>&2

Ve ilk örnekte stream1'in stream1'e yönlendirilmesine izin verilmez (ve çok yararlı değildir).

Umarım yardımcı olur.


24
Yani yerli pencere kabuğu ile imkansız
fanatik

7
@fantastory Mümkün, dbenham Windows toplu
jeb

97
Her şeyin "Hayır" olarak özetlenebileceğini öğrenmek için bu yazıyı okuduğuma inanamıyorum.
Charles McKelvey

1
İkinci mekanizma "çoğaltma işlemek" ne olacak? Ben 3<&2denedim (GT yerine LT not edin) ve sonra 3>errors.txt. Ancak bu kötü bir şekilde sona erdi - sonraki tüm stderr çıktıları yakalandı errors.txt(yani - diğer komutlardan da!).
Tomasz Gandor

for /f "delims=" %%v in ('dir') do echo %%v>>file.txtYine de kullanabilirsiniz .
scriptmastere02

32

UNIX tee komutunun ( http://unxutils.sourceforge.net adresinde bulunan ) Windows sürümünü kullanmanız yeterlidir :

mycommand > tee outpu_file.txt

STDERR çıkışına da ihtiyacınız varsa, aşağıdakileri kullanın. STDOUT içine STDERR çıkışı (birincil akımı) bir araya getirir.
2>&1

mycommand 2>&1 | tee output_file.txt

3
PowerShell Tee-Nesne teklifler benzer işlevsellik. Get-Process | Tee-Object -file c: \ scripts \ test.txt
Kevin Obee

Bunu hem powershell'de hem de normal kabukta denedim. 1>tee a.txtstdout'u komutu teeçağırmak yerine adlı bir dosyaya yönlendirir tee. Herkes bu cevabın kendileri için işe yaradığını onaylayabilir mi?
mafu

@mafu Bunu onaylayabilirim.
Cerno

@mafu Yukarıdaki cevap biraz doğru değildir. "|" Borusunu kullanmalısınız üstteki örnekte ">" yerine. Garip bir şekilde, bu durumda STDOUT ve STDERR çıkışının sırası komut satırında karıştırıldı. Alttaki örnek benim için mükemmel çalışıyor.
Cerno

Ayrıca, sourceforge indirme benim için kırıldı. Burada alternatif bir ev sahibi bulundu: wzw.tum.de/public-html/syring/win32/UnxUtilsDist.html (Münih Üniversitesi)
Cerno

9

Çıktıya gerçek zamanlı olarak ihtiyacınız yoksa (yani program yazdığı gibi)

type windows-dir.txt

sonra.


ya da aynı hat (isteminde yararlı) ile: dir > windows-dir.txt & type windows-dir.txt. Bu aynı zamanda bloklar için geçerlidir: ( echo %date% <NL> echo %username% <NL> echo %time% <NL> pause>CON )>test.txt & type test.txt. Ancak, çıktı gerçek zamanlı olarak gerekiyorsa, bunun için örneğin tee aracının bir Windows bağlantı noktasını kullanabilirsiniz …
mousio


6

Evet, konsolda (ekran) ve bir dosyada tek bir komut çıktısı göstermenin bir yolu vardır. Örneğinizi kullanarak şunu kullanın ...

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

Detaylı açıklama:

FORKomut birden çok kez başvurulan edilebilir bir değişken, bir komuta veya metin çıktısı ayrıştırır.

Gibi bir komut için, DIR /Başağıdaki örnekte gösterildiği gibi tek tırnak içine alın. Değiştir DIR /Bistediğiniz komutu ile metin.

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

Metin görüntülemek için, aşağıdaki örnekte gösterildiği gibi metni çift tırnak içine alın.

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

... ve satır sarma ile ...

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

Çıktının yalnızca konsolda (ekran) olmasını istediğiniz zamanlarınız varsa ve diğer zamanlar yalnızca dosyaya ve diğer zamanların ikisine de gönderildiyse, aşağıda gösterildiği gibi bir değişkeni kullanarak FOR döngüsünün "DO" yan tümcesini belirtin %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

Bunun delims=yerine kullanmalısınız .
scriptmastere02

3
command > file >&1

Tamponu bok doldurmadan değil, toplu iş çalıştırmanıza izin verdiğiniz için verileri ekrana yazmazsanız daha hızlıdır. Hata ayıklama yapıyorsanız,> dosya sözdizimini kullanmazdım.
Random Developer

@andynormancx yup, CMD'den kesip yapıştırmak yerine bunu yazmayı unuttu.
Rastgele Geliştirici

Ben sözdizimi bir windows komut istemi altında çalışmak için alamadım ve bunun yerine type komutu ile gitti.
JamesEggers

& 2 çalışıyor ancak dosyayı test ettiğimde oluşturulmuyor.
JamesEggers

5
"dir> file.txt> & 2" yaparsam file.txt oluşturulmuyor. Dizinin çıktısı konsolda yankılanıyor ancak dosya oluşturulmuyor. "> & 2" mevcut olmadığında dosya oluşturulur.
JamesEggers

2

Çıktı dosyasını değiştirmek yerine eklemek istiyorsanız,

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

veya

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

2

Benim seçeneğim şuydu:

İletiyi alan ve hem konsola hem de günlük dosyasına gönderme işlemini otomatikleştiren bir alt yordam oluşturun.

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

Mesaja bir değişken eklerseniz, altyordamına göndermeden önce içindeki tırnak işaretlerini kaldırdığınızdan emin olun, aksi takdirde toplu işinizi vidalayabilir. Tabii ki bu sadece yankı için işe yarıyor.


VAY EVET! Bunu gerçekten seviyorum !! Yine de üç değişiklik yaptım, umarım onları beğenirsiniz. 1) Ben setlocal enabledelayedexpansionsadece yerine setlocal 2) Logfile değişkeni için gecikmeli genişleme kullanın, bu yüzden altyordam >> !logfile!yerine >> %logfile%. Bu şekilde, bir kod bloğu içinden çağrıldığında çalışır (bir if ifadesinde olduğu gibi). 3) "Değişken mesaj" satırını kaldırdım çünkü fazladan değişkene gerek yok. Zaten var, bu $~1yüzden echo $~1her iki yankı komutu için de var .
Nate

2

Hem cmd ekranına hem de günlüğe gerçek zamanlı çıktı işleyebilen basit bir C # konsolu yaptım

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

Toplu iş dosyası kullanımı, Unix'i nasıl kullandığınızla aynıdır tee

foo | tee xxx.log

Ve burada https://github.com/iamshiao/Tee derlemek için bir araç yoksa Tee.exe içeren depo



0

"Tomas R" tarafından sağlanan çözüm OP sorusu için mükemmel çalışıyor ve yerel olarak mevcut.

Deneyin: chkdsk c:> output.txt | output.txt yazın

Çıktı bu komut dosyaya seri çıktı alır tamamlanma yüzdesi içerir, bu nedenle biraz dağınık görünecektir (yani metin ilerledikçe eklenir). Bu, STDOUT'a (ekran) çıktı alan bitlerde gerçekleşmez. Aynı komutu yeniden yönlendirme yapmadan yaparsanız böyle olur.


-3

Bence bu çizgiler boyunca bir şey istiyorsun:

echo Your Msg> YourTxtFile.txt

Veya yeni bir satır istiyorsanız:

echo Your Msg>> YourTxtFile.txt

Bu komutlar günlükler için mükemmeldir.

Not: Bu bazen bilgisayarımdaki tüm metin dosyasını aksar ve değiştirir.

Başka bir Not: Dosya yoksa, dosyayı oluşturur.


1
hayır, OP çıktıyı bir dosyaya ve ekrana almak istedi . Seninki sadece dosyaya yazıyor. (Ve >edilir tasarlanmış dosyanın üzerine yazmak için kullanın. >>Etmek ekleme )
Stephan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.