Bagaimana cara mendapatkan hasil dari perintah dalam variabel di windows?


132

Saya mencari untuk mendapatkan hasil dari perintah sebagai variabel dalam skrip batch Windows (lihat bagaimana mendapatkan hasil dari perintah dalam bash untuk setara dengan skrip bash). Solusi yang akan berfungsi dalam file bat. Lebih disukai, tetapi solusi scripting windows umum lainnya juga diterima.


9
John, sangat sulit menemukan pertanyaan yang sangat berguna ini. Bisa tolong pertimbangkan untuk menambahkan kalimat alternatif seperti Cara menangkap para keluaran dari aa Program ke dalam variabel dalam file Windows batch?
Piotr Dobrogost

3
Google menampilkan halaman ini di peringkat ke-3.
René Nyffenegger


@MichaelFreidgeim pertanyaan ini sebenarnya ditanyakan 2 tahun sebelum duplikat itu - tetapi ada beberapa duplikat dari pertanyaan ini. Lihat komentar di stackoverflow.com/questions/6359820/…
icc97

1
@ icc97, "Kemungkinan duplikat" adalah cara untuk membersihkan - untuk menutup pertanyaan serupa dan menyimpannya dengan jawaban terbaik. Tanggal tidak penting. Lihat meta.stackexchange.com/questions/147643/... Jika Anda setuju bahwa itu membutuhkan klarifikasi, silakan pilih meta.stackexchange.com/questions/281980/… Jika Anda melihat beberapa duplikat, Anda harus memilih satu sebagai duplikat dan memilih untuk menutup yang lain .
Michael Freidgeim

Jawaban:


34

Jika Anda harus menangkap semua output perintah, Anda dapat menggunakan batch seperti ini:

@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

Semua jalur output disimpan dalam VAR yang dipisahkan dengan "!".

@ John: apakah ada kegunaan praktis untuk ini? Saya pikir Anda harus menonton PowerShell atau bahasa pemrograman lain yang mampu melakukan tugas skrip dengan mudah (Python, Perl, PHP, Ruby)


Jawaban baris tunggal akan menyelesaikan kasus spesifik yang saya miliki. Saya baru saja menemukan ada opsi multi-line (atau opsi single line yang lebih mudah). Saya kira kemampuan file bat tidak begitu bagus. Kebutuhan untuk itu adalah untuk skrip kelelawar yang membungkus aplikasi Java. Membangun jalan setapak terutama.
John Meagher

Berhati-hatilah dengan itu. GWT juga mencoba menggunakan file batch untuk memulai Java dengan classpath tertentu, yang gagal mengerikan segera setelah Anda mendapatkan direktori dengan karakter non-ASCII (dalam hal ini adalah rumah saya :)). Mereka sejak menulis ulang itu dengan VBS.
Joey

25
apakah ada kegunaan praktis untuk ini? Apa Anda sedang bercanda? Ini digunakan sepanjang waktu di shell lain (semua GNU / Linux saya kira) dan ini sangat berguna.
Piotr Dobrogost

1
@PiotrDobrogost Saya pikir apa yang dia coba katakan adalah bahwa skrip bash adalah peninggalan yang mengerikan di masa lalu (Anda perlu menggunakan for loop hanya untuk menangkap output dari suatu program? Serius?), Dan jika Anda pernah sampai pada intinya di mana Anda merasa perlu menggunakan variabel, Anda harus menggunakan sesuatu yang lebih modern seperti PowerShell.
Ajedi32

3
Ada penggunaan praktis, sebenarnya ... agak. Saya ingin menggunakan skrip PowerShell untuk menemukan jalur Visual Studio tertentu, tetapi hal yang saya butuhkan dari jalur itu adalah file batch yang mengatur sekelompok env vars sehingga saya dapat memanggil editbin ... Jadi saya perlu menemukan path dan mendapatkannya kembali ke contoh panggilan cmdsehingga saya bisa menjalankannya di sana. ... Ya, ini sama mengerikannya dengan suara. Visual Studio terkadang membuat saya ingin menangis. @ Ajedi32 Saya pikir Anda bermaksud mengatakan bahwa skrip batch adalah peninggalan yang mengerikan di masa lalu. ;)
jpmc26

85

Rendah hati untuk perintah telah mengumpulkan beberapa kemampuan menarik selama bertahun-tahun:

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

Perhatikan bahwa "delims="menimpa ruang default dan pembatas tab sehingga output dari perintah tanggal akan melahap sekaligus.

Untuk menangkap output multi-line, pada dasarnya masih bisa menjadi satu-liner (menggunakan variabel lf sebagai pembatas dalam variabel yang dihasilkan):

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%

Untuk menangkap ekspresi yang disalurkan, gunakan ^|:

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

1
Seperti jawaban @ PabloG, ini hanya akan berfungsi untuk mendapatkan baris keluaran terakhir dari perintah, "date / t" dalam kasus ini.
John Meagher

11
Saya menemukan jawaban Anda hanya berfungsi ketika saya menggunakan tanda persentase ganda, yaituFOR /F "delims=" %%i IN ('date /t') DO set today=%%i
Rabarberski

18
@ Ramabarki: Jika Anda mengetikkan forperintah langsung pada baris perintah, Anda menggunakan satu %. Jika Anda menggunakannya dalam file batch, Anda gunakan %%.
indiv

@tardate: Bisakah Anda jelaskan seperti apa bentuk skripnya, jika perlu dilewati argumen dengan %, misalnya:for /f "delims=" %%i in ('date +%F_%H-%M-%S') do set now=%%i
dma_k

1
@degenerate Perintah ini valid asalkan dateperintah yang digunakan berasal dari Cygwin. Saya setuju saya seharusnya menyebutkan itu.
dma_k

24

Untuk mendapatkan direktori saat ini, Anda dapat menggunakan ini:

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

Ini menggunakan file temp, jadi ini bukan yang paling cantik, tapi tentu saja berhasil! 'CD' menempatkan direktori saat ini di 'tmpFile', 'SET' memuat konten tmpFile.

Berikut ini solusi untuk beberapa baris dengan "array's":

@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

Tetapi Anda mungkin ingin mempertimbangkan untuk pindah ke shell yang lebih kuat atau membuat aplikasi untuk hal ini. Ini memperluas kemungkinan file batch sedikit.


Apakah ada variasi yang akan berfungsi untuk menangkap beberapa baris dari perintah?
John Meagher

6
Untuk mendapatkan direktori saat ini Anda dapat menggunakan echo% CD%
Joe

9

Anda perlu menggunakan SETperintah dengan parameter /Pdan mengarahkan output Anda ke sana. Misalnya, lihat http://www.ss64.com/nt/set.html . Akan berfungsi untuk CMD, tidak yakin tentang file .BAT

Dari komentar ke pos ini:

Tautan itu memiliki perintah " Set /P _MyVar=<MyFilename.txt" yang mengatakan akan diatur _MyVarke baris pertama dari MyFilename.txt. Ini dapat digunakan sebagai " myCmd > tmp.txt" dengan " set /P myVar=<tmp.txt". Tetapi itu hanya akan mendapatkan baris pertama dari output, tidak semua output


2
Tautan itu memiliki perintah "Set / P _MyVar = <MyFilename.txt" yang mengatakan itu akan mengatur _MyVar ke baris pertama dari MyFilename.txt. Ini dapat digunakan sebagai "myCmd> tmp.txt" dengan "set / P myVar = <tmp.txt". Tetapi itu hanya akan mendapatkan baris pertama dari output, tidak semua output.
John Meagher

Jawaban ini untuk pemula seperti saya

5

Contoh untuk mengatur dalam variabel lingkungan "V" file terbaru

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

dalam file batch Anda harus menggunakan awalan ganda dalam variabel loop:

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

2
Saya telah melihat pendekatan ini sebelumnya, tetapi tampaknya sangat berantakan. Ia juga memiliki masalah bahwa ia hanya akan menangkap garis keluaran terakhir dari perintah dalam variabel.
John Meagher

3

Cukup gunakan hasil dari FORperintah. Misalnya (di dalam file batch):

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

Anda dapat menggunakan %%Isebagai nilai yang Anda inginkan. Sama seperti ini: %%I.

Dan di muka %%Itidak memiliki spasi atau karakter CR dan dapat digunakan untuk perbandingan !!


2

Jika Anda mencari solusi yang disediakan di Menggunakan hasil perintah sebagai argumen di bash?

maka di sini adalah kodenya:

@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
  • Ini akan memanggil dirinya sendiri dengan hasil perintah CD, sama seperti pwd.
  • Ekstraksi string pada parameter akan mengembalikan nama file / folder.
  • Dapatkan isi folder ini dan tambahkan ke filename.txt

[Kredit] : Terima kasih atas semua jawaban lain dan beberapa penggalian di halaman perintah Windows XP .


2
@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%"

Terima kasih telah mengirim jawaban! Sementara cuplikan kode dapat menjawab pertanyaan, tetap bagus untuk menambahkan beberapa informasi tambahan, seperti menjelaskan, dll.
j0k

2

Saya ingin menambahkan komentar ke solusi di atas:

Semua sintaks ini bekerja dengan baik JIKA PERINTAH ANDA DITEMUKAN DALAM JALAN atau JIKA PERINTAH ADALAH cmdpath TANPA RUANG ATAU KARAKTER KHUSUS.

Tetapi jika Anda mencoba menggunakan perintah yang dapat dieksekusi yang terletak di folder yang jalurnya berisi karakter khusus, maka Anda harus menyertakan jalur perintah Anda menjadi tanda kutip ganda (") dan kemudian sintaks FOR / F tidak bekerja.

Contoh:

$ 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.

atau

$ 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.

atau

`$ 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.

Dalam hal itu, satu-satunya solusi yang saya temukan untuk menggunakan perintah dan menyimpan hasilnya dalam sebuah variabel adalah dengan mengatur (sementara) direktori default ke salah satu dari perintah itu sendiri:

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%

Hasilnya kemudian benar:

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

Tentu saja dalam contoh di atas, saya berasumsi bahwa skrip batch saya terletak di folder yang sama dengan salah satu perintah yang dapat dieksekusi sehingga saya dapat menggunakan sintaks "% ~ d0% ~ p0". Jika ini bukan kasus Anda, maka Anda harus menemukan cara untuk menemukan jalur perintah Anda dan mengubah direktori default ke jalurnya.

NB: Bagi mereka yang bertanya-tanya, perintah sampel yang digunakan di sini (untuk memilih folder) adalah FOLDERBROWSE.EXE. Saya menemukannya di situs web f2ko.de ( http://f2ko.de/en/cmd.php ).

Jika ada yang memiliki solusi yang lebih baik untuk perintah semacam itu yang dapat diakses melalui jalur yang kompleks, saya akan sangat senang mendengarnya.

Gilles


Anda dapat mengawali perintah Anda dengan CALL. UNTUK / F tidak berfungsi jika path memiliki spasi
jeb

@ jeb: Terima kasih banyak! Sekarang kode saya < CALL "%SOURCEDIR%\FOLDERBROWSE" ... "quoted parameters"> berfungsi dengan baik.
Gilles Maisonneuve

1

Anda dapat menangkap semua output dalam satu variabel, tetapi garis-garis akan dipisahkan oleh karakter pilihan Anda (# dalam contoh di bawah), bukan CR-LF yang sebenarnya.

@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%

Versi kedua, jika Anda perlu mencetak isinya baris demi baris. Ini mengambil keuntungan dari kenyataan bahwa tidak akan ada garis duplikat output dari "dir / b", jadi mungkin tidak berfungsi dalam kasus umum.

@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=!
    )
)

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

hasilnya adalah 'TXT: hola'


0

Anda harus menggunakan forperintah, berikut ini sebuah contoh:

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

dan Anda dapat menggunakan call :output "Command goes here"maka output akan berada dalam %output%variabel.

Catatan: Jika Anda memiliki output perintah multiline, alat ini akan setmenampilkan output ke baris terakhir dari perintah multiline Anda.


-1

Silakan merujuk ke http://technet.microsoft.com/en-us/library/bb490982.aspx ini yang menjelaskan apa yang dapat Anda lakukan dengan output perintah.


1
Artikel itu hanya membahas pengalihan dan topik terkait. Itu tidak menjawab pertanyaan tentang bagaimana mengambil output dari satu perintah dan memasukkannya ke dalam variabel.
John Meagher

3
Menggunakan jawaban saya, saya telah datang dengan ini: git pull>0 set /P RESULTVAR=<0 edit: Saya kira, saya tidak tahu bagaimana menggunakan jeda baris di sini ... setiap perintah pada baris itu sendiri.
RibeiroBreno
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.