输出文件时使用Powershell环境变量作为字符串
Using Powershell environmental variables as strings when outputting files
我正在使用 Get-WindowsAutopilotInfo 生成计算机的序列号和哈希码,并将该信息导出为 CSV。
这是我常用的代码:
new-item "c:\Autopilot_Export" -type directory -force
Set-Location "C:\Autopilot_Export"
Get-WindowsAutopilotInfo.ps1 -OutputFile Autopilot_CSV.csv
Robocopy C:\Autopilot_Export \Zapp\pc\Hash_Exports /copyall
这会将名为“Autopilot_CSV.csv”的 CSV 文件输出到 C:\Autopilot_Export
目录,然后 Robocopy 将其复制到上面列出的 Hash_Exports 文件夹内的网络共享驱动器。在上面的代码中,如果我手动输入“test”、“123”、“ABC”等并替换“Autopilot_CSV”,它也会在所有这些名称下输出一个 CSV。所以看起来 Get-WindowsAutopilotInfo 将创建一个 CSV 文件并使用您传递给它的任何字符串保存文件名。太好了。
但是,我在多台不同的计算机上 运行 这个脚本,我希望导出的 CSV 被命名为它所在的机器独有的名称 运行 这样我就可以轻松识别它一次它被复制了。我正在尝试将环境变量 $env:computername
的值作为 CSV 的字符串输入传递,但它不起作用。
这是我尝试使用的代码:
new-item "c:\Autopilot_Export" -type directory -force
Set-Location "C:\Autopilot_Export"
Get-WindowsAutopilotInfo.ps1 -OutputFile $env:computername.csv
Robocopy C:\Autopilot_Export C:\Users\danieln\Desktop /copyall
此代码根本不生成 CSV 文件。为什么不呢?
我只是对 Powershell 中如何使用环境变量有基本的误解吗? $env:computername
似乎是 return 计算机名称的字符串,但我无法将其传递到 Get-WindowsAutopilotInfo 并保存它,但如果我手动 将 工作输入一个字符串作为输入。
我也试过将它设置为一个变量 $computername = [string]$env:computername
并只是在 .CSV 之前传递 $computername
并且这似乎也不起作用。根据文档,环境变量显然已经是字符串。
我是不是漏掉了什么?
谢谢!
双引号似乎有效。冒号在powershell参数中比较特殊
echo hi | set-content "$env:computername.csv"
dir
Directory: C:\users\me\foo
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/11/2021 1:02 PM 4 COMP001.csv
冒号很特殊。例如在开关参数中:
get-childitem -force:$true
实际上,它试图找到一个 属性 名为 csv:
echo hi | Set-Content $env:COMPUTERNAME.length
dir
Directory: C:\Users\me\foo
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/11/2021 3:04 PM 4 8
基本上传递一个字符串而不是变量:
write-host $env:computername.csv
# output: (no output - looking for a variable called "computername.csv" instead of "computername")
尝试以下语法:
$filename = "$($env:computername).csv"
write-host $filename
# output: MYPCNAME.csv
shows the effective solution: use "..."
-quoting, i.e. an expandable string 明确.
在命令参数周围使用"..."
显式是一个好习惯字符串 包含 变量引用(例如 "$HOME/projects"
)或子表达式(例如 "./folder/$(Get-Date -Format yyyy-MM)"
)
虽然这样的复合字符串参数通常不需要双引号[1] - 因为它们 隐含地 被视为 "..."
-封闭 - 在某些情况下它们 do 和 when 它们的作用并不明显,因此很难记住:
详细介绍了令人惊讶的复杂规则,但这里有 两个值得注意的陷阱:
如果复合参数 以 子表达式 ($(...)
) 开头,其输出将作为单独的参数传递;例如Write-Output $(Get-Location)/folder
将 两个 参数传递给 Write-Output
:$(Get-Location)
的结果和文字 /folder
如果复合参数 以 开头,变量引用 and 后跟 语法上的内容看起来 (a) 属性 访问 (例如,$PSVersionTable.PsVersion
)或 (b) 方法调用(例如,$PSHome.Tolower()
)它被 执行,即作为一个 表达式(而不是被认为是一个变量引用后跟文字部分)。
旁白 #1:这样的参数不一定是 字符串 ,但无论数据类型是 属性 值还是方法调用return值恰好是。
旁白#2:以开头的复合字符串 带引号的字符串(无论是单引号还是双引号quoted) not 工作,因为开头的引用字符串也被认为是 expression,就像 属性 访问和方法调用一样,这样之后的内容再次作为单独的参数传递。因此,如果复合字符串以 unquoted 子字符串或非表达式变量引用开头,则只能拥有由带引号和不带引号的混合子字符串组成的复合字符串。 [2]
后者是本例中发生的事情:
Unquoted $env:computername.csv
被解释为尝试访问 a 属性 named csv
存储在(环境)变量 $env:computername
中的对象上,并且由于存储的 [string]
实例没有 csv
属性,表达式的计算结果为 $null
.
通过强制 PowerShell通过"..."
将此值解释为可扩展字符串,通常的interpolation rules适用,这意味着.csv
确实被视为 文字 (因为 属性 访问需要在可扩展字符串中使用 $(...)
)。
[1] 引用 是 包含 元字符 的字符串所必需的,例如空格。
对于要处理的值 verbatim,'...'
引号是更好的选择(有关 PowerShell 字符串文字的概述,请参阅 this answer 的底部)。
此外,既不使用双引号也不使用单引号和 单独 `
转义元字符是另一种选择(例如 Write-Output C:\Program` Files
.
[2] 例如,Write-Output a"b`t"'`c'
和 Write-Output $HOME"b`t"'`c'
按预期工作,而 Write-Output "b`t"'`c'
和 Write-Output $HOME.Length"b`t"'`c'
没有(后两者各传递 3 个参数)。解决方法是使用 单个 "..."
字符串,必要时使用内部 `
转义(例如 Write-Output "${HOME}b`t``c"
)或使用字符串连接表达式+
包含在 (...)
中(例如 Write-Output ($HOME + "b`t" + '`c')
)
我正在使用 Get-WindowsAutopilotInfo 生成计算机的序列号和哈希码,并将该信息导出为 CSV。
这是我常用的代码:
new-item "c:\Autopilot_Export" -type directory -force
Set-Location "C:\Autopilot_Export"
Get-WindowsAutopilotInfo.ps1 -OutputFile Autopilot_CSV.csv
Robocopy C:\Autopilot_Export \Zapp\pc\Hash_Exports /copyall
这会将名为“Autopilot_CSV.csv”的 CSV 文件输出到 C:\Autopilot_Export
目录,然后 Robocopy 将其复制到上面列出的 Hash_Exports 文件夹内的网络共享驱动器。在上面的代码中,如果我手动输入“test”、“123”、“ABC”等并替换“Autopilot_CSV”,它也会在所有这些名称下输出一个 CSV。所以看起来 Get-WindowsAutopilotInfo 将创建一个 CSV 文件并使用您传递给它的任何字符串保存文件名。太好了。
但是,我在多台不同的计算机上 运行 这个脚本,我希望导出的 CSV 被命名为它所在的机器独有的名称 运行 这样我就可以轻松识别它一次它被复制了。我正在尝试将环境变量 $env:computername
的值作为 CSV 的字符串输入传递,但它不起作用。
这是我尝试使用的代码:
new-item "c:\Autopilot_Export" -type directory -force
Set-Location "C:\Autopilot_Export"
Get-WindowsAutopilotInfo.ps1 -OutputFile $env:computername.csv
Robocopy C:\Autopilot_Export C:\Users\danieln\Desktop /copyall
此代码根本不生成 CSV 文件。为什么不呢?
我只是对 Powershell 中如何使用环境变量有基本的误解吗? $env:computername
似乎是 return 计算机名称的字符串,但我无法将其传递到 Get-WindowsAutopilotInfo 并保存它,但如果我手动 将 工作输入一个字符串作为输入。
我也试过将它设置为一个变量 $computername = [string]$env:computername
并只是在 .CSV 之前传递 $computername
并且这似乎也不起作用。根据文档,环境变量显然已经是字符串。
我是不是漏掉了什么?
谢谢!
双引号似乎有效。冒号在powershell参数中比较特殊
echo hi | set-content "$env:computername.csv"
dir
Directory: C:\users\me\foo
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/11/2021 1:02 PM 4 COMP001.csv
冒号很特殊。例如在开关参数中:
get-childitem -force:$true
实际上,它试图找到一个 属性 名为 csv:
echo hi | Set-Content $env:COMPUTERNAME.length
dir
Directory: C:\Users\me\foo
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2/11/2021 3:04 PM 4 8
基本上传递一个字符串而不是变量:
write-host $env:computername.csv
# output: (no output - looking for a variable called "computername.csv" instead of "computername")
尝试以下语法:
$filename = "$($env:computername).csv"
write-host $filename
# output: MYPCNAME.csv
"..."
-quoting, i.e. an expandable string 明确.
在命令参数周围使用"..."
显式是一个好习惯字符串 包含 变量引用(例如 "$HOME/projects"
)或子表达式(例如 "./folder/$(Get-Date -Format yyyy-MM)"
)
虽然这样的复合字符串参数通常不需要双引号[1] - 因为它们 隐含地 被视为 "..."
-封闭 - 在某些情况下它们 do 和 when 它们的作用并不明显,因此很难记住:
如果复合参数 以 子表达式 (
$(...)
) 开头,其输出将作为单独的参数传递;例如Write-Output $(Get-Location)/folder
将 两个 参数传递给Write-Output
:$(Get-Location)
的结果和文字/folder
如果复合参数 以 开头,变量引用 and 后跟 语法上的内容看起来 (a) 属性 访问 (例如,
$PSVersionTable.PsVersion
)或 (b) 方法调用(例如,$PSHome.Tolower()
)它被 执行,即作为一个 表达式(而不是被认为是一个变量引用后跟文字部分)。旁白 #1:这样的参数不一定是 字符串 ,但无论数据类型是 属性 值还是方法调用return值恰好是。
旁白#2:以开头的复合字符串 带引号的字符串(无论是单引号还是双引号quoted) not 工作,因为开头的引用字符串也被认为是 expression,就像 属性 访问和方法调用一样,这样之后的内容再次作为单独的参数传递。因此,如果复合字符串以 unquoted 子字符串或非表达式变量引用开头,则只能拥有由带引号和不带引号的混合子字符串组成的复合字符串。 [2]
后者是本例中发生的事情:
Unquoted
$env:computername.csv
被解释为尝试访问 a 属性 namedcsv
存储在(环境)变量$env:computername
中的对象上,并且由于存储的[string]
实例没有csv
属性,表达式的计算结果为$null
.通过强制 PowerShell通过
"..."
将此值解释为可扩展字符串,通常的interpolation rules适用,这意味着.csv
确实被视为 文字 (因为 属性 访问需要在可扩展字符串中使用$(...)
)。
[1] 引用 是 包含 元字符 的字符串所必需的,例如空格。
对于要处理的值 verbatim,'...'
引号是更好的选择(有关 PowerShell 字符串文字的概述,请参阅 this answer 的底部)。
此外,既不使用双引号也不使用单引号和 单独 `
转义元字符是另一种选择(例如 Write-Output C:\Program` Files
.
[2] 例如,Write-Output a"b`t"'`c'
和 Write-Output $HOME"b`t"'`c'
按预期工作,而 Write-Output "b`t"'`c'
和 Write-Output $HOME.Length"b`t"'`c'
没有(后两者各传递 3 个参数)。解决方法是使用 单个 "..."
字符串,必要时使用内部 `
转义(例如 Write-Output "${HOME}b`t``c"
)或使用字符串连接表达式+
包含在 (...)
中(例如 Write-Output ($HOME + "b`t" + '`c')
)