Prompt dei comandi di Windows: come posso ottenere l'output di un comando in una variabile di ambiente?


59

Voglio avere una variabile di ambiente che contiene il giorno della settimana in cmd.exe.

Quando eseguo questo comando ottengo il risultato che desidero.

C:\Users\tisc> powershell (get-date).dayofweek
Friday

Qui sto cercando di archiviare il risultato in una variabile di ambiente.

C:\Users\tisc> set dow = powershell (get-date).dayofweek

Ma quando provo a ottenerlo non ottengo la stringa come volevo.

C:\Users\tisc> set dow
DoW=0
dow = powershell (get-date).dayofweek

Il mio obiettivo è utilizzare la variabile in un file batch per alcuni script di backup.

Risposte:


87

Puoi usare qualcosa come:

$env:DOW = "foo"

3
Non capisco perché questo è stato contrassegnato negativamente, conosci un modo migliore per impostare le variabili di ambiente?
Ion Todirel,

2
+1 Funziona benissimo per me nello scenario di cui avevo bisogno. PowerShell -Command $env:Note = 'Elevate'; (New-Object -com 'Shell.Application').ShellExecute('cmd.exe', '/k %*', '', 'runas')
David Ruhmann,

14
@IonTodirel Perché questo persiste solo nello spazio del processo.
JohnD,

finalmente ora capisco come impostare RAILS_ENV in PowerShell
cablato

E poi come lo emetti per assicurarti che abbia funzionato?
CodyBugstein il

22

È necessario eseguire entrambi i comandi in PowerShell poiché PowerShell è più che in grado di manipolare le variabili ambientali.

Vale a dire:

$dow = (get-date).dayofweek
[Environment]::SetEnvironmentVariable("DOW", $dow, "Machine")

o

[Environment]::SetEnvironmentVariable("DOW", $dow, "User")

A proposito, il tuo script non funziona perché tutto ciò che ottieni è il codice di ritorno di PowerShell, non i dati che produce. Potrebbe esserci un modo per farlo funzionare, ma alla fine è inutile rispetto al semplice utilizzo di uno script PowerShell corretto.

Per completezza, ecco un bell'articolo di Microsoft su PowerShell e variabili ambientali:

Creazione e modifica di variabili d'ambiente

Aggiornamento: dopo aver esaminato questa soluzione con @ syneticon-dj in chat, sembra che il problema che si presenta usando questo metodo sia che un prompt dei comandi deve essere ricaricato prima che rifletta i cambiamenti nelle variabili ambientali che sono avvenuti esternamente.

Non hai fornito molti dettagli su ciò che stai facendo, ma se questa è l'unica ragione per cui stai lanciando PowerShell, il mio suggerimento reale potrebbe rivedere come stai facendo le cose.

O l'intero processo con PowerShell o hai preso in considerazione l'utilizzo di attività pianificate? È possibile pianificare le attività in base al giorno della settimana.


Il file batch verrà eseguito ogni giorno e verrà eseguito dalle attività pianificate. Invece sto pensando di lavorare in PowerShell. Ma sono ancora più principiante in PowerShell di cmd. E in questo momento ho delle difficoltà con un semplice comando. Ma posso fare una nuova domanda a riguardo, forse è una domanda facile per te :) EDIT: L'ho capito. Era come eseguire un programma con alcuni parametri.
Tim

Nemmeno io sono bravo in PowerShell, ma vale la pena imparare. Per cominciare è solo meglio in quasi tutti i modi, ma è anche il modo in cui Microsoft (e così altri produttori) si stanno muovendo.
Dan

1
Inoltre, tieni presente che il suggerimento di @ Dan sopra imposta le variabili di ambiente in modo abbastanza permanente (nel contesto Macchina o Utente). Se si omette il terzo parametro, è possibile impostarlo solo per il processo corrente, che a volte è più desiderabile.
Per Lundberg,

20

Credo che l'impostazione della variabile d'ambiente all'interno di PowerShell con [Environment]::SetEnvironmentVariablecome suggerito da Dan è inutile, perché si sarebbe neanche perdere il contenuto della variabile al momento della cessazione di PowerShell se si è scelto il contesto temporanea "processo" o non lo avremo entro l'ambiente file batch ancora se si sceglie il contesto permanente "macchina" o "utente", ovvero, a meno che l'intero script non sia scritto in PowerShell, in cui il problema non si presenta in primo luogo:

C:\Users\myuser> echo %DOW%
%DOW%

C:\Users\myuser> powershell
Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. Alle Rechte vorbehalten.

PS C:\Users\myuser> $dow = (get-date).dayofweek
PS C:\Users\myuser> [Environment]::SetEnvironmentVariable("DOW", $dow, "User")
PS C:\Users\myuser> [Environment]::SetEnvironmentVariable("DOW", $dow, "Process")
PS C:\Users\myuser> exit

C:\Users\myuser> echo %DOW%
%DOW%

C:\Users\myuser>

È possibile utilizzare il forcomando come soluzione alternativa per analizzare l'output del comando PowerShell e inserirlo in una variabile:

  for /F "usebackq tokens=1" %%i in (`powershell ^(get-date^).dayofweek`) do set DOW=%%i

Nota i caratteri del cursore ^utilizzati per sfuggire ai caratteri speciali tra parentesi nella chiamata di PowerShell.

Se lo si sta testando dalla riga di comando e non all'interno di un contesto di file batch, è necessario sostituire i %%riferimenti alla variabile precedente con %:

C:\Users\myuser> for /F "usebackq tokens=1" %i in (`powershell ^(get-date^).dayofw
eek`) do set DOW=%i

C:\Users\myuser> set DOW=Friday

C:\Users\myuser>

No, questo non è corretto. Il mio esempio seguente imposta le variabili ambientali "normali" che sono accessibili da qualsiasi file batch ecc.
Dan

@Dan Credo che ti sbagli, ho provato [Environment]::SetEnvironmentVariable("DOW", $dow, "user")a eseguire le impostazioni all'interno di una sessione PowerShell in esecuzione ma non era presente nella sessione cmd del mio genitore al termine di PowerShell
the-wabbit

La formattazione ha rovinato tutto, ma non hai definito $ dow. L'esecuzione del mio esempio in uno script Powershell memorizza una normale variabile ambientale come previsto.
Dan,

1
@Dan BTW: non mi dispiace il downvoting, ma va notato che l'approccio dimostrato fa chiaramente quello che l'interrogante ha chiesto , quindi anche se ci fosse un approccio più elegante, sarebbe comunque una valida soluzione al problema.
the-wabbit il

1
@ the-wabbit Sembra un comportamento normale in Windows. Anche se si aggiornano le variabili di ambiente globali, solo i processi avviati dall'aggiornamento riconosceranno la modifica. Dal momento che stai parlando di un processo genitore , deve essere iniziato prima della modifica. La stessa cosa accade con il SETprompt dei comandi. Prova ad avviare un bambino cmd.exee vedrai la stessa cosa. Tuttavia, il comportamento che si sta verificando in PowerShell è perché l'aggiornamento delle variabili di ambiente tramite le classi .NET non influisce sul processo corrente.
jpmc26,

4

Se si trattasse di me, e lo script genitore deve essere uno script di shell, mi basta fare un invocazione sfacciato di PowerShell nello script .CMD come:

set DOW=
for /f %%D in ('%SystemRoot%\System32\WindowsPowerShell\V1.0\powershell.exe -NoLogo -NoProfile -Command Write-Host -Object ^(Get-Date^).DayOfWeek;') do set DOW=%%D

Potrebbe essere necessario controllare i criteri di esecuzione di PowerShell (cmdlet Set-ExecutionPolicy).


3

O se sei sposato con questo nella vecchia shell, salta completamente PowerShell.

Usa la variabile% date% ed espandi il giorno dall'abbreviazione che fornisce (questo potrebbe essere influenzato dalle impostazioni del formato della data regionale):

C:\> echo %date%
Thu 09/05/2013

Prendi il primo token nella risposta ed espandi su quello:

C:\> type dayofweek.cmd
@echo off
for /f %%A in ("%date%") do set DAYOFWEEK=%%A
if "%DAYOFWEEK%" == "Mon" set DAYOFWEEK=Monday
if "%DAYOFWEEK%" == "Tue" set DAYOFWEEK=Tuesday
if "%DAYOFWEEK%" == "Wed" set DAYOFWEEK=Wednesday
if "%DAYOFWEEK%" == "Thu" set DAYOFWEEK=Thursday
if "%DAYOFWEEK%" == "Fri" set DAYOFWEEK=Friday
if "%DAYOFWEEK%" == "Sat" set DAYOFWEEK=Saturday
if "%DAYOFWEEK%" == "Sun" set DAYOFWEEK=Sunday
echo.%DAYOFWEEK%
C:\>
C:\> dayofweek
Thursday

1
Windows 10 non mostrerà il DOW in% DATE%: H: \> echo% date% 20/03/2019
Raúl Salinas-Monteagudo

1

In realtà, quando si inserisce qualcosa di simile al seguente in un file .ps1 (diciamo, t.ps1) e lo si chiama da una sessione CMD con PowerShell -File t.ps1... funziona bene.

$DateAndTime = (get-date -UFormat "%Y%m%d_%H%M%S")[Environment]::SetEnvironmentVariable("DateAndTime", $DateAndTime, "Machine")

Ma non per la sessione CMD da cui è stato chiamato lo script t.ps1. In una nuova sessione CMD otteniamo:

D:> echo% DateAndTime% ==> 20120208_123106

Immagino che dobbiamo scoprire come fare qualcosa di simile export T=datein una sessione CMD.


1

Se si desidera che il file batch acceda alle variabili di ambiente impostate da un comando PowerShell eseguito da quel file batch, è possibile utilizzare la soluzione alternativa seguente:

Fai in modo che lo script di PowerShell crei un file batch secondario mysub.bat, che contenga righe "set variabile = valore" ed esegui quel file batch mysub.bat dal file batch principale subito dopo il comando PowerShell.

Utilizzare il metodo WriteAllLines anziché i metodi di output di PowerShell predefiniti in modo che il file batch secondario non venga generato con il formato di codifica UTF-8.

Esempio

main.bat:

REM main.bat first line
powershell -Command "[System.IO.File]::WriteAllLines(\".\mysub.bat\", \"set VARIABLE=VALUE\");"
.\mysub.bat
echo VARIABLE=%VARIABLE%
REM expected output: VARIABLE=VALUE
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.