Командная строка 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>

Нет, это неверно Мой пример ниже устанавливает «нормальные» переменные среды, которые доступны из любого пакетного файла и т. Д.
— Дан

@ Дан, я думаю, что вы ошибаетесь, я пытался установить [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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.