it-swarm.asia

عرض أمر Windows إخراج موجه وإعادة توجيهه إلى ملف

كيف يمكنني تشغيل تطبيق لسطر الأوامر في موجه أوامر Windows وعرض الإخراج وإعادة توجيهه إلى ملف في نفس الوقت؟

على سبيل المثال ، إذا كنت سأقوم بتشغيل الأمر dir > test.txt ، فسيؤدي ذلك إلى إعادة توجيه الإخراج إلى ملف يسمى test.txt دون عرض النتائج.

كيف يمكنني كتابة أمر لعرض الإخراج و إعادة توجيه الإخراج إلى ملف في موجه أوامر Windows ، على غرار الأمر tee في يونكس؟

332
Ammu

للتوسع في إجابة دافور ، يمكنك استخدام PowerShell مثل هذا:

powershell "dir | tee test.txt"

إذا كنت تحاول إعادة توجيه إخراج exe في الدليل الحالي ، فأنت بحاجة إلى استخدام .\ في اسم الملف ، على سبيل المثال:

powershell ".\something.exe | tee test.txt"
124
Saxon Druce

تمكنت من العثور على حل/حل بديل لإعادة توجيه الإخراج إلى ملف ثم إلى وحدة التحكم:

dir > a.txt | type a.txt

حيث dir هو الأمر الذي يحتاج إلى إعادة توجيه الإخراج ، a.txt ملف حيث يتم تخزين الإخراج.

124
NSPKUWCExi2pr8wVoGNk

يوجد منفذ Win32 للأمر Unix tee ، يقوم بذلك بالضبط. انظر http://unxutils.sourceforge.net/ أو http://getgnuwin32.sourceforge.net/

90
Brian Rasmussen

تحقق من ذلك: wintee

لا حاجة ل cygwin.

لقد صادفت وأبلغ عن بعض المشكلات.

كما يمكنك التحقق من unxutils لأنه يحتوي على نقطة الإنطلاق (وليس هناك حاجة إلى cygwin) ، ولكن حذار أن إخراج EOL هي مثل UNIX هنا.

أخيرًا وليس آخرًا ، إذا كان لديك PowerShell ، فيمكنك تجربة Tee-Object. اكتب get-help tee-object في وحدة التحكم PowerShell لمزيد من المعلومات.

47
Davor Josipovic

@ tori3852

لقد وجدت ذلك

dir > a.txt | type a.txt

لم تنجح (الأسطر القليلة الأولى من قائمة dir فقط - تشك في وجود نوع من عملية التهيئة والجزء الثاني ، تم إنهاء الأمر "type" قبل أن تكتمل القائمة الرهيبة؟) ، لذا بدلاً من ذلك استخدمت:

dir > z.txt && type z.txt

التي فعلت - الأوامر التسلسلية ، واحد يكمل قبل أن يبدأ الثاني.

42
Andy Welch

تطبيق وحدة تحكم C # بسيط سيفعل الخدعة:

using System;
using System.Collections.Generic;
using System.IO;

namespace CopyToFiles
{
    class Program
    {
        static void Main(string[] args)
        {
            var buffer = new char[100];
            var outputs = new List<TextWriter>();

            foreach (var file in args)
                outputs.Add(new StreamWriter(file));

            outputs.Add(Console.Out);

            int bytesRead;
            do
            {
                bytesRead = Console.In.ReadBlock(buffer, 0, buffer.Length);
                outputs.ForEach(o => o.Write(buffer, 0, bytesRead));
            } while (bytesRead == buffer.Length);

            outputs.ForEach(o => o.Close());
        }
    }
}

لاستخدام هذا الأمر ، عليك فقط توجيه الأمر source إلى البرنامج وتوفير مسار أي ملفات تريد تكرار الإخراج إليها. فمثلا:

dir | CopyToFiles files1.txt files2.txt 

سيتم عرض نتائج dir وكذلك تخزين النتائج في كل من files1.txt و files2.txt.

لاحظ أنه لا يوجد الكثير (أي شيء!) في طريق معالجة الأخطاء أعلاه ، وقد لا يكون دعم ملفات متعددة مطلوبًا بالفعل.

22
Richard

للأسف لا يوجد شيء من هذا القبيل.

تحتوي تطبيقات وحدة التحكم في Windows فقط على مؤشر إخراج واحد. (حسنًا ، هناك نوعان STDOUT ، STDERR لكن لا يهم هنا) > يعيد توجيه الإخراج المكتوب عادةً إلى مقبض وحدة التحكم إلى مقبض ملف.

إذا كنت ترغب في الحصول على نوع من الإرسال المتعدد ، فيجب عليك استخدام تطبيق خارجي يمكنك تحويل الإخراج إليه. ثم يمكن لهذا التطبيق الكتابة إلى ملف وإلى وحدة التحكم مرة أخرى.

21
Daniel Rikowski

هذا يعمل ، رغم أنه قبيح بعض الشيء:

dir >_ && type _ && type _ > a.txt

إنها أكثر مرونة قليلاً من بعض الحلول الأخرى ، حيث إنها تعمل بيانًا تلو الآخر حتى تتمكن من استخدامه للإلحاق أيضًا. أستخدم هذا قليلاً في ملفات الدُفعات لتسجيل الرسائل وعرضها:

ECHO Print line to screen and log to file.  >_ && type _ && type _ >> logfile.txt

نعم ، يمكنك فقط تكرار عبارة ECHO (مرة واحدة للشاشة والمرة الثانية إعادة التوجيه إلى ملف السجل) ، لكن يبدو الأمر سيئًا ويعد مشكلة صيانة قليلاً. على الأقل بهذه الطريقة ، لا يتعين عليك إجراء تغييرات على الرسائل في مكانين.

لاحظ أن _ مجرد اسم ملف قصير ، لذلك ستحتاج إلى التأكد من حذفه في نهاية ملف الدُفعات الخاص بك (إذا كنت تستخدم ملف دفعي).

18
MTS

mtee هي أداة صغيرة والتي تعمل بشكل جيد للغاية لهذا الغرض. إنه مجاني ، والمصدر مفتوح ، ويعمل فقط.

يمكنك العثور عليه في http://www.commandline.co.uk .

يستخدم في ملف دفعي لعرض الإخراج وإنشاء ملف سجل في وقت واحد ، يبدو بناء الجملة كما يلي:

    someprocess | mtee /+ mylogfile.txt

حيث/+ يعني إلحاق الإخراج.

هذا يفترض أنك قمت بنسخ mtee في مجلد موجود في المسار ، بالطبع.

15
Mark

وأنا أتفق مع برايان راسموسين ، وميناء unxutils هو أسهل طريقة للقيام بذلك. في ملفات الدُفعات قسم صفحته صفحات البرمجة النصية يوفر Rob van der Woude ثروة من المعلومات عن استخدام أوامر MS-DOS و CMD. اعتقدت أنه ربما يكون لديه حل أصلي لمشكلتك ، وبعد البحث من هناك ، وجدت TEE.BAT ، والذي يبدو أنه تطبيق لغة دفعية من MS-DOS تمامًا. إنه ملف دفعي ذو مظهر معقد إلى حد كبير ولا يزال ميلي هو استخدام منفذ unxutils.

9
Steve Crane

أرغب في التوسع قليلاً في برنامج Saxon Druce إجابة ممتازة .

كما هو مذكور ، يمكنك إعادة توجيه إخراج الملف التنفيذي في الدليل الحالي مثل:

powershell ".\something.exe | tee test.txt"

ومع ذلك ، يسجل هذا فقط stdout إلى test.txt. إنه لا يسجل أيضًا stderr.

الحل الواضح هو استخدام شيء مثل هذا:

powershell ".\something.exe 2>&1 | tee test.txt"

ومع ذلك ، لن يعمل هذا مع جميع something.exes. بعض something.exes ستفسر 2>&1 على أنها وسيطة وتفشل. الحل الصحيح هو بدلاً من ذلك أن يكون لديك علامة اقتباس أحادية حول رمز something.exe فقط ، وهي مفاتيح وسيطات ، مثل ذلك:

powershell ".\something.exe --switch1 --switch2 … arg1 arg2 …" 2>&1 | tee test.txt
8
アリスター

إذا كان لديك cygwin في مسار بيئة Windows ، فيمكنك استخدام:

 dir > a.txt | tail -f a.txt
7
jkdba

dir 1>a.txt 2>&1 | type a.txt

هذا سيساعد على إعادة توجيه كل من STDOUT و STDERR

6
rashok

كنت أبحث أيضًا عن نفس الحل ، وبعد قليل من المحاولة ، تمكنت من تحقيق ذلك بنجاح في Command Prompt. إليكم الحل:

@Echo off
for /f "Delims=" %%a IN (xyz.bat) do (
%%a > _ && type _ && type _ >> log.txt
)
@Echo on

حتى أنه يلتقط أي أمر PAUSE كذلك.

4
Koder101

إرسال الإخراج إلى وحدة التحكم ، إلحاق سجل وحدة التحكم ، وحذف الإخراج من الأمر الحالي

dir  >> usb-create.1 && type usb-create.1 >> usb-create.log | type usb-create.1 && del usb-create.1
4
Dennis

شيء من هذا القبيل يجب أن تفعل ما تحتاجه؟

%DATE%_%TIME% > c:\a.txt & type c:\a.txt
ipconfig >> c:\a.txt & type c:\a.txt
ping localhost >> c:\a.txt & type c:\a.txt
pause
3
Richard K

فيما يلي نموذج لما استخدمته استنادًا إلى أحد الإجابات الأخرى

@echo off
REM SOME CODE
set __ERROR_LOG=c:\errors.txt
REM set __IPADDRESS=x.x.x.x

REM Test a variable
if not defined __IPADDRESS (
     REM Call function with some data and terminate
     call :TEE %DATE%,%TIME%,IP ADDRESS IS NOT DEFINED
     goto :EOF
)

REM If test happens to be successful, TEE out a message and end script.
call :TEE Script Ended Successful
goto :EOF


REM THE TEE FUNCTION
:TEE
for /f "tokens=*" %%Z in ("%*") do (
     >  CON ECHO.%%Z
     >> "%__ERROR_LOG%" ECHO.%%Z
     goto :EOF
)
3
Ed Radke

أعلم أن هذا موضوع قديم جدًا ، لكن في الإجابات السابقة ، لا يوجد تنفيذ كامل لوقت حقيقي تم كتابته في Batch. حالي أدناه هو برنامج نصي مختلط Batch-JScript يستخدم قسم JScript فقط للحصول على الإخراج من الأمر piped ، ولكن تتم معالجة البيانات في قسم Batch. تتمتع هذه الطريقة بميزة أن أي مبرمج دفعي قد يعدل هذا البرنامج ليناسب احتياجات معينة. يقوم هذا البرنامج أيضًا بمعالجة إخراج أمر CLS الذي تم إنتاجه بواسطة ملفات دفعية أخرى بشكل صحيح ، أي أنه يمسح الشاشة عند اكتشاف إخراج أمر CLS.

@if (@CodeSection == @Batch) @then


@echo off
setlocal EnableDelayedExpansion

rem APATee.bat: Asynchronous (real time) Tee program, Batch-JScript hybrid version
rem Antonio Perez Ayala

rem The advantage of this program is that the data management is written in Batch code,
rem so any Batch programmer may modify it to fit their own needs.
rem As an example of this feature, CLS command is correctly managed

if "%~1" equ "" (
   echo Duplicate the Stdout output of a command in the screen and a disk file
   echo/
   echo anyCommand ^| APATee teeFile.txt [/A]
   echo/
   echo If /A switch is given, anyCommand output is *appended* to teeFile.txt
   goto :EOF
)

if "%2" equ ":TeeProcess" goto TeeProcess

rem Get the output of CLS command
for /F %%a in ('cls') do set "cls=%%a"

rem If /A switch is not provided, delete the file that receives Tee output
if /I "%~2" neq "/A" if exist %1 del %1

rem Create the semaphore-signal file and start the asynchronous Tee process
echo X > Flag.out
if exist Flag.in del Flag.in
Cscript //nologo //E:JScript "%~F0" | "%~F0" %1 :TeeProcess
del Flag.out
goto :EOF

:TeeProcess
   rem Wait for "Data Available" signal
   if not exist Flag.in goto TeeProcess
   rem Read the line sent by JScript section
   set line=
   set /P line=
   rem Set "Data Read" acknowledgement
   ren Flag.in Flag.out
   rem Check for the standard "End Of piped File" mark
   if "!line!" equ ":_EOF_:" exit /B
   rem Correctly manage CLS command
   if "!line:~0,1!" equ "!cls!" (
      cls
      set "line=!line:~1!"
   )
   rem Duplicate the line in Stdout and the Tee output file
   echo(!line!
   echo(!line!>> %1
goto TeeProcess


@end


// JScript section

var fso = new ActiveXObject("Scripting.FileSystemObject");
// Process all lines of Stdin
while ( ! WScript.Stdin.AtEndOfStream ) {
   // Read the next line from Stdin
   var line = WScript.Stdin.ReadLine();
   // Wait for "Data Read" acknowledgement
   while ( ! fso.FileExists("Flag.out") ) {
      WScript.Sleep(10);
   }
   // Send the line to Batch section
   WScript.Stdout.WriteLine(line);
   // Set "Data Available" signal
   fso.MoveFile("Flag.out", "Flag.in");
}
// Wait for last "Data Read" acknowledgement
while ( ! fso.FileExists("Flag.out") ) {
      WScript.Sleep(10);
}
// Send the standard "End Of piped File" mark
WScript.Stdout.WriteLine(":_EOF_:");
fso.MoveFile("Flag.out", "Flag.in");
3
Aacini
@echo on

set startDate=%date%
set startTime=%time%

set /a sth=%startTime:~0,2%
set /a stm=1%startTime:~3,2% - 100
set /a sts=1%startTime:~6,2% - 100


fullprocess.bat > C:\LOGS\%startDate%_%sth%.%stm%.%sts%.LOG | fullprocess.bat

سيؤدي ذلك إلى إنشاء ملف سجل مع التاريخ الحالي ، ويمكنك خطوط الأسطر أثناء العملية

2
7thSphere

هذا هو الاختلاف في السابق الجواب بواسطة MTS ، لكنه يضيف بعض الوظائف التي قد تكون مفيدة للآخرين. إليك الطريقة التي استخدمتها:

  • يتم تعيين أمر كمتغير ، يمكن استخدامه لاحقًا خلال التعليمات البرمجية ، لإخراجها إلى إطار الأوامر وإلحاقها بملف سجل ، باستخدام set _Temp_Msg_Cmd=
    • نجا الأمر إعادة توجيه باستخدام حرف الجزرة ^ بحيث لا يتم تقييم الأوامر في البداية
  • يتم إنشاء ملف مؤقت باسم ملف مماثل لملف الدُفعات الذي يتم تشغيله يسمى %~n0_temp.txt والذي يستخدم بناء جملة ملحق معلمة سطر الأوامر%~n0 للحصول على اسم ملف الدُفعات.
  • يتم إلحاق الإخراج بملف سجل منفصل %~n0_log.txt

هنا تسلسل الأوامر:

  1. يتم إرسال رسائل الإخراج والخطأ إلى الملف المؤقت ^> %~n0_temp.txt 2^>^&1
  2. محتوى الملف المؤقت هو كليهما:
    • يتم إلحاق ملف السجل ^& type %~n0_temp.txt ^>^> %~n0_log.txt
    • الإخراج إلى نافذة الأوامر ^& type %~n0_temp.txt
  3. يتم حذف الملف المؤقت مع الرسالة ^& del /Q /F %~n0_temp.txt

هنا هو المثال:

set _Temp_Msg_Cmd= ^> %~n0_temp.txt 2^>^&1 ^& type %~n0_temp.txt ^>^> %~n0_log.txt ^& type %~n0_temp.txt ^& del /Q /F %~n0_temp.txt

بهذه الطريقة يمكن ببساطة إلحاق الأمر بعد الأوامر اللاحقة في ملف دفعي يبدو أكثر نظافة:

echo test message %_Temp_Msg_Cmd%

يمكن إضافة هذا إلى نهاية الأوامر الأخرى أيضًا. بقدر ما أستطيع أن أقول أنها ستعمل عندما يكون للرسائل أسطر متعددة. على سبيل المثال ، يخرج الأمر التالي سطرين إذا كانت هناك رسالة خطأ:

Net Use M: /D /Y %_Temp_Msg_Cmd%

2
ClearBlueSky85

إذا كنت في CLI ، فلماذا لا تستخدم حلقة FOR لـ "DO" لكل ما تريد:

for /F "delims=" %a in ('dir') do @echo %a && echo %a >> output.txt

مورد كبير على Windows CMD للحلقات: https://ss64.com/nt/for_cmd.html المفتاح هنا هو تعيين المحددات (delims) ، والتي من شأنها أن تفكك كل سطر من الإخراج ، إلى شيء. بهذه الطريقة لن ينكسر الافتراضي للمساحة البيضاء. ٪ a عبارة عن خطاب تعسفي ، لكن يتم استخدامه في قسم "do" للقيام ، حسناً ... بعمل شيء باستخدام الأحرف التي تم تحليلها في كل سطر. في هذه الحالة ، يمكننا استخدام علامات الضم (&&) لتنفيذ أمر الصدى الثاني لإنشاء أو إلحاق (>>) بملف من اختيارنا. أكثر أمانًا للحفاظ على هذا الترتيب لأوامر DO في حالة وجود مشكلة في كتابة الملف ، سنحصل على الأقل على الصدى إلى وحدة التحكم أولاً. علامة (@) الموجودة أمام أول صدى تمنع وحدة التحكم من إظهار أمر الارتداد نفسه ، وبدلاً من ذلك فقط تعرض نتيجة الأمر وهي عرض الأحرف في٪ a. خلاف ذلك سترى:

حجم الصدى في محرك الأقراص [x] هو Windows
وحدة التخزين في محرك الأقراص [x] هي Windows

UPDATE:/F يتخطى الأسطر الفارغة والإصلاح الوحيد هو تصفية الخرج مسبقًا بإضافة حرف إلى كل سطر (ربما مع أرقام الأسطر عبر أمر البحث). حل هذا في CLI ليس سريعًا أو جميلًا. أيضًا ، لم أقم بتضمين STDERR ، لذا فإليك التقاط الأخطاء أيضًا:

for /F "delims=" %a in ('dir 2^>^&1') do @echo %a & echo %a >> output.txt

إعادة توجيه رسائل الخطأ

توجد العلامات (^) هناك للهروب من الرموز بعدها ، لأن الأمر عبارة عن سلسلة يتم تفسيرها ، على عكس القول ، بإدخالها مباشرة في سطر الأوامر.

1
Had To Ask

يمكنني استخدام روتين فرعي الدفعي مع عبارة "for" للحصول على سطر الأوامر إخراج سطر واحد في كل مرة وكلاهما كتابة هذا السطر إلى ملف وإخراجها إلى وحدة التحكم.

@echo off
set logfile=test.log

call :ExecuteAndTee dir C:\Program Files

Exit /B 0

:ExecuteAndTee
setlocal enabledelayedexpansion
echo Executing '%*'
  for /f "delims=" %%a in ('%* 2^>^&1') do (echo.%%a & echo.%%a>>%logfile%)
endlocal
Exit /B 0
1
Cody Barnes

البديل هو أن تضيف stdout إلى stderr ضمن برنامجك:

في جافا:

System.setOut(new PrintStream(new TeeOutputStream(System.out, System.err)));

ثم ، في batchfile dos: Java program > log.txt

سينتقل stdout إلى ملف السجل وسيظهر stderr (نفس البيانات) على وحدة التحكم.

0
The Coordinator

هناك صيغة أخرى تتمثل في تقسيم الأنبوب ، ثم إعادة توجيه الإخراج كما تريد.

    @echo off
    for /f "tokens=1,* delims=:" %%P in ('findstr /n "^"') do (
      echo.%%Q
      echo.%%Q>&3
    )
    @exit/b %errorlevel%

حفظ ما سبق إلى ملف .bat. يقوم بتقسيم إخراج النص على filestream 1 إلى filestream 3 أيضًا ، والذي يمكنك إعادة توجيهه حسب الحاجة. في الأمثلة أدناه ، اتصلت بالبرنامج النصي أعلاه splitPipe.bat ...

    dir | splitPipe.bat  1>con  2>&1  3>my_stdout.log

    splitPipe.bat 2>nul < somefile.txt
0
user3726414

أقوم بتثبيت Perl على معظم أجهزتي لذلك إجابة باستخدام Perl: tee.pl

my $file = shift || "tee.dat";
open $output, ">", $file or die "unable to open $file as output: $!";
while(<STDIN>)
{
    print $_;
    print $output $_;
}
close $output;

دير | Perl tee.pl أو dir | Perl tee.pl dir.bat

الخام وغير مجربة.

0
DannyK

تماما مثل يونيكس.

dir | tee a.txt

يعمل على نظام التشغيل Windows XP ، يتطلب تثبيت mksnt.

يتم عرضه على موجه وكذلك إلحاق الملف.

0
user2346926

هذا يعمل في الوقت الحقيقي ولكن أيضا بشع والأداء بطيء. لم يتم اختباره بشكل جيد أيضًا:

@echo off
cls
SET MYCOMMAND=dir /B
ECHO File called 'test.bat' > out.txt
for /f "usebackq delims=" %%I in (`%MYCOMMAND%`) do (
  ECHO %%I
  ECHO %%I >> out.txt
) 
pause
0
djangofan

كيف يمكنني عرض وإعادة توجيه الإخراج إلى ملف. لنفترض أنه في حالة استخدام الأمر dos ، dir> test.txt ، سيعيد هذا الأمر توجيه الإخراج إلى ملف test.txt دون عرض النتائج. كيفية كتابة أمر لعرض الإخراج وإعادة توجيه الإخراج إلى ملف باستخدام DOS ، على سبيل المثال ، windows command Prompt ، وليس في UNIX/LINUX.

قد تجد هذه الأوامر في biterscripting ( http://www.biterscripting.com ) مفيدة.

var str output
lf > $output
echo $output                            # Will show output on screen.
echo $output > "test.txt"               # Will write output to file test.txt.
system start "test.txt"                 # Will open file test.txt for viewing/editing.
0
P M

يساعدك المتابعة إذا كنت تريد شيئًا ما يظهر بالفعل على الشاشة - حتى إذا تمت إعادة توجيه الملف الدفعي إلى ملف. ربما يستخدم الجهاز CON أيضًا في حالة إعادة توجيهه إلى ملف

مثال:

ECHO first line on normal stdout. maybe redirected
ECHO second line on normal stdout again. maybe redirected
ECHO third line is to ask the user. not redirected  >CON
ECHO fourth line on normal stdout again. maybe redirected

انظر أيضًا وصفًا جيدًا لإعادة التوجيه: http://www.p-dd.com/chapter7-page14.html

0
Baresi der Libero