Prompt de comando do Windows: como faço para obter a saída de um comando em uma variável de ambiente?

59

Quero ter uma variável de ambiente que contenha o dia da semana em cmd.exe.

Quando executo esse comando, obtenho o resultado desejado.

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

Aqui estou tentando armazenar o resultado em uma variável de ambiente.

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

Mas quando tento obtê-lo, não entendo a corda como queria.

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

Meu objetivo é usar a variável em um arquivo em lotes para alguns scripts de backup.

Tim
fonte

Respostas:

87

Você pode usar algo como:

$env:DOW = "foo"
Ion Todirel
fonte
3
Não entendo por que isso foi sinalizado negativamente, você conhece um melhor para definir variáveis ​​de ambiente?
Ion Todirel
2
+1 Isso funciona muito bem para mim no cenário que eu precisava. PowerShell -Command $env:Note = 'Elevate'; (New-Object -com 'Shell.Application').ShellExecute('cmd.exe', '/k %*', '', 'runas')
David Ruhmann
14
@IonTodirel Porque isso persiste apenas no espaço do processo.
JohnD
Finalmente agora eu entendo definir RAILS_ENV howto no PowerShell
wired00
E então, como você o produz para garantir que funcionou?
CodyBugstein 03/03
22

Você deve executar os dois comandos no PowerShell, pois o PowerShell é mais do que capaz de manipular variáveis ​​ambientais.

Ou seja:

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

ou

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

A propósito, seu script não funciona porque tudo o que você recebe é o código de retorno do PowerShell, não os dados que ele produz. Pode haver uma maneira de fazê-lo funcionar, mas, em última análise, é inútil comparado ao uso de um script do PowerShell adequado.

Para completar, aqui está um bom artigo da Microsoft no PowerShell e variáveis ​​ambientais:

Criando e modificando variáveis ​​de ambiente

Atualização: Depois de revisar esta solução com @ syneticon-dj no chat, parece que o problema que você enfrenta usando esse método é que um prompt de comando deve ser recarregado antes de refletir as alterações nas variáveis ​​ambientais que ocorreram externamente.

Você não forneceu muitos detalhes sobre o que está fazendo, mas se esse é o único motivo pelo qual você está lançando o PowerShell, minha sugestão real seria revisar como você está fazendo as coisas.

Todo o seu processo usando o PowerShell ou você já pensou em usar tarefas agendadas? Você pode agendar tarefas com base no dia da semana.

Dan
fonte
O arquivo em lotes será executado todos os dias e a partir das tarefas agendadas. Estou pensando em trabalhar no PowerShell. Mas sou ainda mais novato em PowerShell do que cmd. E agora estou tendo dificuldades com um simples comando. Mas posso fazer uma nova pergunta sobre essa, talvez seja fácil para você :) EDIT: Eu descobri. Era como executar um programa com alguns parâmetros.
Tim
Também não sou bom no PowerShell, mas vale a pena aprender. Para começar, é apenas melhor em quase todos os aspectos, mas também é o caminho da Microsoft (e de outros fabricantes).
Dan
11
Além disso, observe que a sugestão de @ Dan acima define as variáveis ​​de ambiente permanentemente (no contexto de Máquina ou Usuário). Se você deixar de fora o terceiro parâmetro, poderá configurá-lo apenas para o processo atual, que às vezes é mais desejável.
Per Lundberg
20

Acredito que definir a variável de ambiente de dentro do PowerShell com [Environment]::SetEnvironmentVariablecomo sugerido por Dan é inútil, porque você quer perder o conteúdo da variável após o término do PowerShell se você escolheu o contexto temporário "processo" ou não tê-lo dentro do ambiente do seu arquivo de lote ainda se você escolher o contexto permanente "máquina" ou "usuário" - ou seja, a menos que todo o script seja escrito no PowerShell, em que o problema não surgiria em primeiro lugar:

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>

Você pode usar o forcomando como uma solução alternativa para analisar a saída do seu comando do PowerShell e colocá-lo em uma variável:

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

Observe os caracteres de interpolação ^usados ​​para escapar dos caracteres especiais entre parênteses na chamada do PowerShell.

Se você estiver testando a partir da linha de comando e não de um contexto de arquivo em lote, será necessário substituir as %%referências à variável anterior por %:

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>
o wabbit
fonte
Não, isso está incorreto. Meu exemplo abaixo variáveis ambientais 'normais' conjuntos que são acessíveis a partir de qualquer arquivo de lote etc.
Dan
@ Dan Eu acredito que você está enganado, eu tentei configuração [Environment]::SetEnvironmentVariable("DOW", $dow, "user")de dentro de uma sessão do PowerShell em execução, mas não estava presente na minha sessão cmd pai após a rescisão do PowerShell
o wabbit
A formatação estragou tudo, mas você não definiu $ dow. A execução do meu exemplo em um script do Powershell armazena uma variável ambiental normal conforme o esperado.
Dan
11
@ Dan BTW: Eu não me importo com o voto negativo, mas deve-se notar que a abordagem demonstrada faz claramente o que o solicitante solicitou ; portanto, mesmo que houvesse uma abordagem mais elegante, ainda seria uma solução válida para o problema.
the-wabbit
11
@ the-wabbit Isso parece um comportamento normal no Windows. Mesmo se você atualizar as variáveis ​​de ambiente global, apenas os processos iniciados desde a atualização reconhecerão a alteração. Como você está falando de um processo pai , ele deve ter sido iniciado antes da alteração. O mesmo acontece com o SETprompt de comando. Tente começar um filho cmd.exee você verá a mesma coisa. O comportamento que você vê no PowerShell é que a atualização das variáveis ​​de ambiente por meio das classes .NET não afeta o processo atual.
jpmc26
4

Se fosse eu, e o script pai tivesse que ser um shell, eu faria uma invocação atrevida do PowerShell no script .CMD como:

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

Pode ser necessário verificar sua política de execução do PowerShell (cmdlet Set-ExecutionPolicy).

Simon Catlin
fonte
3

Ou, se você é casado com isso no shell antigo, pule completamente o PowerShell.

Use a variável% date% e expanda o dia a partir da abreviação que ela fornece (isso pode ser afetado pelas configurações de formato de data regional):

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

Pegue o primeiro token na resposta e expanda:

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
M Jeremy Carter
fonte
11
O Windows 10 não mostrará a DOW em% DATE%: H: \> eco% date% 20/03/2019
Raúl Salinas-Monteagudo
1

Na verdade, ao colocar algo como o abaixo em um arquivo .ps1 (por exemplo t.ps1) e chamá-lo de uma sessão CMD com o PowerShell -File t.ps1... funciona bem.

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

Mas não para a sessão CMD da qual o script t.ps1 foi chamado. Em uma nova sessão de CMD, obtemos:

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

Acho que temos que descobrir como fazer algo parecido export T=dateem uma sessão de CMD.

Edgar
fonte
1

Se você deseja que seu arquivo em lote acesse variáveis ​​de ambiente definidas por um comando do PowerShell, execute a partir desse arquivo em lotes, use a seguinte solução alternativa:

Faça seu script do PowerShell criar um arquivo de mysub.batsubbatch,, que contém linhas "set variable = value" e execute esse arquivo de lote mysub.bat a partir do arquivo de lote principal, logo após o comando do PowerShell.

Use o método WriteAllLines em vez dos métodos de saída padrão do PowerShell, para que o arquivo de sub-lote não seja gerado com o formato de codificação UTF-8.

Exemplo

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
user262456
fonte