it-swarm.com.de

Wie erhalte ich das Ergebnis eines Befehls in einer Variablen in Windows?

Ich versuche, das Ergebnis eines Befehls als Variable in einem Windows-Batch-Skript zu erhalten (siehe So erhalten Sie das Ergebnis eines Befehls in Bash für das Bash-Äquivalent) Eine Lösung, die in einer .bat-Datei funktioniert, wird bevorzugt, aber auch andere gängige Windows-Skriptlösungen sind willkommen. 

111
John Meagher

Wenn Sie alle Befehlsausgaben erfassen müssen, können Sie einen Stapel wie folgt verwenden:

@ECHO OFF
IF NOT "%1"=="" GOTO ADDV
SET VAR=
FOR /F %%I IN ('DIR *.TXT /B /O:D') DO CALL %0 %%I
SET VAR
GOTO END

:ADDV
SET VAR=%VAR%!%1

:END

Alle Ausgangszeilen werden in VAR getrennt mit "!" Gespeichert.

@John: Gibt es eine praktische Verwendung dafür? Ich denke, Sie sollten sich PowerShell oder eine andere Programmiersprache ansehen, die Skriptaufgaben leicht ausführen kann (Python, Perl, PHP, Ruby)

29
PabloG

Der bescheidene Befehl for hat im Laufe der Jahre einige interessante Fähigkeiten gesammelt:

D:\> FOR /F "delims=" %i IN ('date /t') DO set today=%i
D:\> echo %today%
Sat 20/09/2008

Beachten Sie, dass "delims=" die Standardbegrenzer für Leerzeichen und Tabulatoren überschreibt, sodass die Ausgabe des Datumsbefehls auf einmal verschlungen wird.

Um mehrzeilige Ausgaben zu erfassen, kann es sich im Wesentlichen immer noch um einen Einzeiler handeln (unter Verwendung der Variablen lf als Trennzeichen in der resultierenden Variablen):

REM NB:in a batch file, need to use %%i not %i
setlocal EnableDelayedExpansion
SET lf=-
FOR /F "delims=" %%i IN ('dir \ /b') DO if ("!out!"=="") (set out=%%i) else (set out=!out!%lf%%%i)
ECHO %out%

Verwenden Sie ^| zum Erfassen eines Pipe-Ausdrucks:

FOR /F "delims=" %%i IN ('svn info . ^| findstr "Root:"') DO set "URL=%%i"
75
tardate

Um das aktuelle Verzeichnis abzurufen, können Sie Folgendes verwenden:

CD > tmpFile
SET /p myvar= < tmpFile
DEL tmpFile
echo test: %myvar%

Es verwendet zwar eine temporäre Datei, ist also nicht die schönste, aber es funktioniert auf jeden Fall! 'CD' legt das aktuelle Verzeichnis in 'tmpFile', 'SET' lädt den Inhalt von tmpFile.

Hier ist eine Lösung für mehrere Zeilen mit "Arrays":

@echo off

rem ---------
rem Obtain line numbers from the file
rem ---------

rem This is the file that is being read: You can replace this with %1 for dynamic behaviour or replace it with some command like the first example i gave with the 'CD' command.
set _readfile=test.txt

for /f "usebackq tokens=2 delims=:" %%a in (`find /c /v "" %_readfile%`) do set _max=%%a
set /a _max+=1
set _i=0
set _filename=temp.dat

rem ---------
rem Make the list
rem ---------

:makeList
find /n /v "" %_readfile% >%_filename%

rem ---------
rem Read the list
rem ---------

:readList
if %_i%==%_max% goto printList

rem ---------
rem Read the lines into the array
rem ---------
for /f "usebackq delims=] tokens=2" %%a in (`findstr /r "\[%_i%]" %_filename%`) do set _data%_i%=%%a
set /a _i+=1
goto readList

:printList
del %_filename%
set _i=1
:printMore
if %_i%==%_max% goto finished
set _data%_i%
set /a _i+=1
goto printMore

:finished

Vielleicht möchten Sie jedoch zu einer anderen, leistungsfähigeren Shell wechseln oder eine Anwendung für dieses Zeug erstellen. Dies erweitert die Möglichkeiten der Batch-Dateien erheblich.

23
Evil Activity

sie müssen den Befehl SET mit dem Parameter /P verwenden und Ihre Ausgabe darauf ausrichten . Siehe beispielsweise http://www.ss64.com/nt/set.html . Funktioniert für CMD, nicht sicher über BAT-Dateien

Aus einem Kommentar zu diesem Beitrag:

Dieser Link hat den Befehl "Set /P _MyVar=<MyFilename.txt", der besagt, dass _MyVar in der ersten Zeile gesetzt wird von MyFilename.txt. Das könnte sein wird als "myCmd > tmp.txt" mit "set /P myVar=<tmp.txt" verwendet. Aber es wird nur Holen Sie sich die erste Zeile der Ausgabe, nicht alle Ausgabe

7
Ilya Kochetov

Beispiel, um in der Umgebungsvariable "V" die neueste Datei festzulegen 

FOR /F %I IN ('DIR *.* /O:D /B') DO SET V=%I

in einer Batchdatei müssen Sie in der Schleifenvariablen ein doppeltes Präfix verwenden:

FOR /F %%I IN ('DIR *.* /O:D /B') DO SET V=%%I
5
PabloG

Verwenden Sie einfach das Ergebnis des Befehls FOR. Zum Beispiel (in einer Batchdatei):

for /F "delims=" %%I in ('dir /b /a-d /od FILESA*') do (echo %%I)

Sie können den %%I als gewünschten Wert verwenden. Einfach so: %%I.

Vorab hat der %%I keine Leerzeichen oder CR-Zeichen und kann für Vergleiche verwendet werden !!

3
Raceableability
@echo off

ver | find "6.1." > nul
if %ERRORLEVEL% == 0 (
echo Win7
for /f "delims=" %%a in ('DIR "C:\Program Files\Microsoft Office\*Outlook.EXE" /B /P /S') do call set findoutlook=%%a
%findoutlook%
)

ver | find "5.1." > nul
if %ERRORLEVEL% == 0 (
echo WinXP
for /f "delims=" %%a in ('DIR "C:\Program Files\Microsoft Office\*Outlook.EXE" /B /P /S') do call set findoutlook=%%a
%findoutlook%
)
echo Outlook dir:  %findoutlook%
"%findoutlook%"
2
Hike

Wenn Sie nach der Lösung suchen, die in angegeben ist, das Ergebnis eines Befehls als Argument in bash verwenden?

dann ist hier der Code:

@echo off
if not "%1"=="" goto get_basename_pwd
for /f "delims=X" %%i in ('cd') do call %0 %%i
for /f "delims=X" %%i in ('dir /o:d /b') do echo %%i>>%filename%.txt
goto end

:get_basename_pwd
set filename=%~n1

:end
  • Dies ruft sich mit dem Ergebnis des CD-Befehls auf, genau wie bei pwd.
  • Die Zeichenkettenextraktion für Parameter gibt den Dateinamen/Ordner zurück.
  • Rufen Sie den Inhalt dieses Ordners ab und hängen Sie ihn an die Dateiname.txt an

[Credits]: Vielen Dank an alle anderen Antworten und einiges Graben auf der Seite Windows XP - Befehle .

2
Gustavo Carreno

Sie können alle Ausgaben in einer Variablen erfassen, die Zeilen werden jedoch durch ein Zeichen Ihrer Wahl (# im Beispiel unten) anstelle eines tatsächlichen CR-LF getrennt.

@echo off
setlocal EnableDelayedExpansion
for /f "delims=" %%i in ('dir /b') do (
    if "!DIR!"=="" (set DIR=%%i) else (set DIR=!DIR!#%%i)
)
echo directory contains:
echo %DIR%

Zweite Version, wenn Sie den Inhalt Zeile für Zeile ausdrucken müssen. Dies profitiert von der Tatsache, dass es keine doppelten Ausgabezeilen von "dir/b" gibt, sodass es im allgemeinen Fall nicht funktioniert.

@echo off
setlocal EnableDelayedExpansion
set count=0
for /f "delims=" %%i in ('dir /b') do (
    if "!DIR!"=="" (set DIR=%%i) else (set DIR=!DIR!#%%i)
    set /a count = !count! + 1
)

echo directory contains:
echo %DIR%

for /l %%c in (1,1,%count%) do (
    for /f "delims=#" %%i in ("!DIR!") do (
        echo %%i
        set DIR=!DIR:%%i=!
    )
)
1
Adam Mitz

Ich möchte den obigen Lösungen eine Bemerkung hinzufügen:

Alle diese Syntaxen funktionieren einwandfrei, wenn Ihr Befehl IS innerhalb des Pfads gefunden wurde oder wenn der Befehl IS einen cmdpath OHNE Leerzeichen OR als Sonderzeichen enthält.

Wenn Sie jedoch versuchen, einen ausführbaren Befehl in einem Ordner zu verwenden, dessen Pfad Sonderzeichen enthält, müssen Sie Ihren Befehlspfad in doppelte Anführungszeichen (") setzen. Dann funktioniert die FOR/F-Syntax nicht.

Beispiele:

$ for /f "tokens=* USEBACKQ" %f in (
    `""F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" Hello '"F:\GLW7\Distrib\System\Shells and scripting"'`
) do echo %f
The filename, directory name, or volume label syntax is incorrect.

oder 

$ for /f "tokens=* USEBACKQ" %f in (
      `"F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe" "Hello World" "F:\GLW7\Distrib\System\Shells and scripting"`
) do echo %f
'F:\GLW7\Distrib\System\Shells' is not recognized as an internal or external command, operable program or batch file.

oder 

`$ for /f "tokens=* USEBACKQ" %f in (
     `""F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" "Hello World" "F:\GLW7\Distrib\System\Shells and scripting"`
) do echo %f
'"F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" "Hello' is not recognized as an internal or external command, operable program or batch file.

In diesem Fall besteht die einzige Lösung, die ich gefunden habe, um einen Befehl zu verwenden und sein Ergebnis in einer Variablen zu speichern, darin, das Standardverzeichnis (vorübergehend) auf das eines Befehls selbst festzulegen:

pushd "%~d0%~p0"
FOR /F "tokens=* USEBACKQ" %%F IN (
    `FOLDERBROWSE "Hello world!" "F:\GLW7\Distrib\System\Layouts (print,display...)"`
) DO (SET MyFolder=%%F)
popd
echo My selected folder: %MyFolder%

Das Ergebnis ist dann korrekt:

My selected folder: F:\GLW7\Distrib\System\OS install, recovery, VM\
Press any key to continue . . .

Im obigen Beispiel gehe ich natürlich davon aus, dass sich mein Batch-Skript im selben Ordner befindet wie der ausführbare Befehl, sodass ich die "% ~ d0% ~ p0" -Syntax verwenden kann. Wenn dies nicht der Fall ist, müssen Sie einen Weg finden, Ihren Befehlspfad zu finden und das Standardverzeichnis in seinen Pfad zu ändern.

Hinweis: Für diejenigen, die sich fragen, ist der hier verwendete Beispielbefehl (zum Auswählen eines Ordners) FOLDERBROWSE.EXE. Ich habe es auf der Website f2ko.de ( http://f2ko.de/de/cmd.php ) gefunden.

Wenn jemand eine bessere Lösung für diese Art von Befehlen hat, die über einen komplexen Pfad zugänglich sind, würde ich mich sehr freuen, von ihm zu hören.

Gilles

1

Sie sollten den Befehl for verwenden. Hier ein Beispiel:

@echo off
rem Commands go here
exit /b
:output
for /f "tokens=* useback" %%a in (`%~1`) do set "output=%%a"

und Sie können call :output "Command goes here" verwenden, dann wird die Ausgabe in der Variablen %output% erfolgen.

Hinweis: Wenn Sie eine Befehlsausgabe haben, die mehrzeilig ist, set setzt dieses Tool die Ausgabe in die letzte Zeile Ihres mehrzeiligen Befehls.

0
Hayz
@echo off
setlocal EnableDelayedExpansion
FOR /F "tokens=1 delims= " %%i IN ('echo hola') DO (
    set TXT=%%i
)
echo 'TXT: %TXT%'

das Ergebnis ist 'TXT: hola'

0
ivan rc