Командная строка Windows: как получить вывод команды в переменную окружения?

59

Я хочу иметь переменную среды, которая содержит день недели в cmd.exe.

Когда я запускаю эту команду, я получаю желаемый результат.

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

Здесь я пытаюсь сохранить результат в переменной окружения.

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

Но когда я пытаюсь получить это, я не получаю строку, как я хотел.

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

Моя цель - использовать переменную в командном файле для некоторых скриптов резервного копирования.

Тим
источник

Ответы:

87

Вы можете использовать что-то вроде:

$env:DOW = "foo"
Ион Тодирель
источник
3
Я не понимаю, почему это было помечено отрицательно, знаете ли вы лучше установить переменные среды?
Ион Тодирел
2
+1 Это прекрасно работает для меня в сценарии, который мне нужен. PowerShell -Command $env:Note = 'Elevate'; (New-Object -com 'Shell.Application').ShellExecute('cmd.exe', '/k %*', '', 'runas')
Дэвид Руманн
14
@IonTodirel Потому что это сохраняется только в пространстве процесса.
JohnD
наконец, теперь я понимаю, как установить RAILS_ENV в powershell
wired00
И как вы выводите его, чтобы убедиться, что оно работает?
CodyBugstein
22

Вы должны запустить обе команды в PowerShell, поскольку PowerShell более чем способен манипулировать переменными среды.

То есть:

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

или же

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

Кстати, ваш скрипт не работает, потому что вы получаете только код возврата PowerShell, а не данные, которые он генерирует. Возможно, есть способ заставить его работать, но в конечном счете это бессмысленно по сравнению с использованием только правильного сценария PowerShell.

Для полноты вот хорошая статья от Microsoft по PowerShell и переменным среды:

Создание и изменение переменных среды

Обновление. Изучив это решение с помощью @ syneticon-dj в чате, вы обнаружите, что проблема, с которой вы сталкиваетесь при использовании этого метода, заключается в том, что необходимо перезагрузить командную строку, прежде чем она отразит изменения переменных среды, которые произошли извне.

Вы не предоставили подробных сведений о том, чем вы занимаетесь, но если это единственная причина, по которой вы запускаете PowerShell, то мое реальное предложение - проанализировать, как вы это делаете.

Либо весь ваш процесс использует PowerShell, либо вместо этого вы решили использовать запланированные задачи? Вы можете планировать задачи в зависимости от дня недели.

Дэн
источник
Пакетный файл будет запускаться каждый день и запускаться из запланированных задач. Я думаю о работе в PowerShell вместо этого. Но я даже больше новичка в powershell, чем cmd. И сейчас у меня трудности с простой командой. Но я могу задать новый вопрос об этом, может быть, это легкий для вас :) РЕДАКТИРОВАТЬ: Я понял это. Это было как запустить программу с некоторыми параметрами.
Тим
Я тоже не силен в PowerShell, но его стоит изучить. Для начала, это просто лучше почти во всех отношениях, но это также и путь Microsoft (и других производителей).
Дан
1
Кроме того, обратите внимание, что предложение @ Dan, приведенное выше, устанавливает переменные окружения довольно постоянно (в контексте Machine или User). Если вы пропустите третий параметр, вы можете установить его только для текущего процесса, что иногда более желательно.
За Лундберг
20

Я считаю , установив переменные окружения внутри PowerShell с [Environment]::SetEnvironmentVariableкак это было предложено Dan бессмысленно, потому что вы либо потерять содержимое переменного по окончанию PowerShell , если вы выбрали временный «процесс» контекст или не иметь его в среде пакетной обработки файла еще если вы выбрали постоянный «машинный» или «пользовательский» контекст - то есть, если весь ваш сценарий не написан в PowerShell, где проблема не возникнет в первую очередь:

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>

Вы можете использовать forкоманду в качестве обходного пути, чтобы проанализировать выходные данные вашей команды PowerShell и поместить ее в переменную:

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

Обратите внимание на символы вставки, ^используемые для экранирования специальных символов в скобках в вызове PowerShell.

Если вы тестируете его из командной строки, а не из контекста пакетного файла, вам нужно будет заменить %%ссылки перед переменными на %:

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>
заместитель Wabbit
источник
Нет, это неверно Мой пример ниже устанавливает «нормальные» переменные среды, которые доступны из любого пакетного файла и т. Д.
Дан
@ Дан, я думаю, что вы ошибаетесь, я пытался установить [Environment]::SetEnvironmentVariable("DOW", $dow, "user")изнутри сеанс PowerShell, но он не присутствовал в моем родительском сеансе cmd после завершения PowerShell
the-wabbit
Форматирование облажалось, но вы не определили $ dow. Выполнение моего примера в скрипте Powershell сохраняет обычную переменную среды, как и ожидалось.
Дан
1
@ Dan BTW: Я не возражаю против понижения голосов, но следует отметить, что продемонстрированный подход четко выполняет то, о чем просил спрашивающий , так что даже если бы существовал более элегантный подход, он все равно был бы правильным решением проблемы.
the-wabbit
1
@ the-wabbit Это звучит как нормальное поведение в Windows. Даже если вы обновите глобальные переменные среды, только процессы, запущенные после обновления , распознают изменение. Поскольку вы говорите о родительском процессе, он должен был начаться до изменения. То же самое происходит SETв командной строке. Попробуйте завести ребенка, cmd.exeи вы увидите то же самое. Однако поведение, которое вы наблюдаете в PowerShell, заключается в том, что обновление переменных среды с помощью классов .NET не влияет на текущий процесс.
jpmc26
4

Если бы это был я, а родительский сценарий должен быть сценарием оболочки, я бы просто сделал дерзкий вызов PowerShell в сценарии .CMD, например:

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

Возможно, вам придется проверить политику выполнения PowerShell (командлет Set-ExecutionPolicy).

Саймон Кэтлин
источник
3

Или, если вы женаты, чтобы делать это в старой оболочке, полностью пропустите PowerShell.

Используйте переменную% date% и разверните день из полученного сокращения (это может зависеть от региональных настроек формата даты):

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

Возьмите первый жетон в ответе и расскажите о нем:

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 не будет отображать DOW в% DATE%: H: \> echo% date% 20/03/2019
Рауль Салинас-Монтеагудо
1

На самом деле, если поместить что-то подобное ниже в файл .ps1 (скажем, t.ps1) и вызвать его из сеанса CMD с PowerShell -File t.ps1... это работает хорошо.

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

Но не для сеанса CMD, откуда был вызван скрипт t.ps1. В новой сессии CMD мы получаем:

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

Я предполагаю, что мы должны выяснить, как сделать что-то вроде export T=dateсеанса CMD.

Эдгар
источник
1

Если вы хотите, чтобы ваш пакетный файл имел доступ к переменным среды, установленным командой PowerShell, из этого пакетного файла, вы можете использовать следующий обходной путь:

Сделайте так, чтобы ваш скрипт PowerShell создал файл mysub.batподпакета, содержащий строки «set variable = value», и запустите этот пакетный файл mysub.bat из основного пакетного файла сразу после команды PowerShell.

Используйте метод WriteAllLines вместо методов вывода PowerShell по умолчанию, чтобы файл подпакета не создавался в формате кодировки UTF-8.

пример

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
источник