Power Shell Get-ChildItem 然后通过管道传输到 Get-Content
Power Shell Get-ChildItem then pipe to Get-Content
我正在尝试检索已知文件名的未知文件路径,然后对该文件名执行 Get-Content
以便我可以对其进行修改。我知道该文件将在 C:\Users$env:UserName\
中,但就我所能及的范围而言(最终用户可能会将其放在更远的地方,例如文档或桌面或其他地方)。
它似乎可以执行 Get-ChildItem
或 Get-Content
,但由于某些原因我不能在同一个脚本中同时执行这两项操作。
总体目标:将 Get-ChildItem 的结果通过管道传递给 Get-Contents 函数,以便我可以修改文件。
这是我的代码:
(Get-ChildItem -Path C:\Users$env:UserName -Filter QA11test.hep) |
Foreach-Object {
$_ # send the current line to output
if($_ -match "SSL/TLS User Cipher Suites=DEFAULT"){
"IP Port=2023"
"Security Option=2"
$Message = "Your host explorer session has been updated."
Msg $env:UserName $Message
exit
} else {
$Message = "Script Failed."
Msg $env:UserName $Message
exit
}
} | Set-Content C:\Users$env:UserName\Telnet\QA11TestSecure.hep
需要帮助!谢谢!
对于如何获取文件及其内容,然后检查文件内容中的任意行,似乎存在一些困惑。我建议不要将其写在大型复合命令中,而是将其分解为不同的样式,以便最大程度地减少管道混乱。有多种方法可以完成相同的任务,有些方法比其他方法更容易遵循,尤其是在调试时。
$fileoutput = @'
IP Port=2023
Security Option=2
'@
$FileToLookAt = Get-ChildItem -Path C:\Users$env:UserName -Recurse -Filter "QA11test.hep" | Get-Content
if ($FileToLookAt)
{
$found = ""
$found = $FileToLookAt | Where-Object {$_ -eq 'SSL/TLS User Cipher Suites=DEFAULT'}
if ($found)
{
$Message = "Your host explorer session has been updated."
Set-Content -Path C:\Users$env:UserName\Telnet\QA11TestSecure.hep -Value $fileoutput -Force
} else
{
$Message = "Script Failed."
}
} else
{
$Message = "QA11test.hep not found."
}
Msg $env:UserName $Message
编辑:好的,确实应该检查 Set-Content 以确保 file/path 存在。假设是这样,这样的事情应该可行。
在最简单的情况下,您需要做的就是使用 Get-Content
命令插入一个管道段:
Get-ChildItem -Path C:\Users$env:UserName -Filter QA11test.hep |
Get-Content | # Send the lines of the input file(s) one by one to ForEach-Object
ForEach-Object { ...
但是,您的方法存在问题:
如果找到文件,则无条件写入输出文件 - 即使未对输入内容进行任何修改。
- 此外,由于代码中的
exit
语句,任何剩余的输入行都从输出文件中省略。
如果找到 no 文件,输出文件要么被创建为一个空文件(0
字节),要么,如果它已经存在, 替换为一个空文件。
相反,我建议使用 一种基于 switch
statement 的方法,它更快、更简洁、更灵活:
值得注意的是,此解决方案仅在找到输入文件时创建/替换输出文件并且对其进行了修改。
Get-ChildItem -Path C:\Users$env:UserName -Filter QA11test.hep | ForEach-Object {
$updated = $false
$newLines = switch -File $_.FullName -Regex { # Loop over all file lines
'SSL/TLS User Cipher Suites=DEFAULT' {
$_, "IP Port=2023", "Security Option=2" # send 2 additional lines
$updated = $true
}
default { $_ } # pass other lines through
}
# Rewrite the file only if modifications were made.
if ($updated) { $newLines | Set-Content C:\Users$env:UserName\Telnet\QA11TestSecure.hep }
# Emit the appropriate status message.
Msg $env:UserName ('Nothing to update.', 'Your host explorer session has been updated.')[$updated]
}
注意:如果您还需要知道是否找到了输入文件 - 无论是否需要更新 - 设置 $found = $true
在脚本块内并在命令后检查它:if (-not $found) { Msg $env:UserName 'QA11test.hep not found' }
switch -File $_.FullName -Regex
逐行读取输入文件,并根据正则表达式条件匹配每一行:
- 如果正则表达式匹配,则输出原始行 (
$_
),以及 2 条附加行;另外,设置标志 $updated
以指示内容已修改。
- 所有其他行(
default
条件行)按原样输出。
$newLines = ...
捕获数组中的(可能修改的)行。
- 请注意,这意味着所有行都一次存储在内存中,但文本文件通常不是问题。
只有设置了$updated
才会写入输出文件(Set-Content
)。
最后,Msg
命令被调用并带有状态适当的消息。
- 注意
('msg1', 'msg2')[$updated]
表达式,它是根据标志选择两个值之一的快捷方式:如果 $updated
是 $true
,则 $true
被强制为数组索引 1
,因此选择 'msg2'
;如果是$false
,索引是0
,选择'msg1'
。
谢谢大家的帮助!
(@mklement0,我将修改它以做一些接近你最后一个 post 所做的事情!这对我很有帮助。)
我从不同的 post 中提取了点点滴滴,这就是我想出的,它可以满足我的需要。
此 PowerShell 脚本获取已知文件的完整路径,"QA11test.hep" 并将其加载到一个变量中供以后使用。然后它会在该文件的内容中搜索特定字符串 "SSL/TLS..etc",如果找到它,它会在找到的行下方添加两行,"Port=2023" 和 "Security Option 2"。然后它获取该新文件并将其添加到 C:\Users\$env:UserName\Desktop\QA11TestSecure.hep 而不更改原始 QA11test.hep 文件。因此,它不是从 get-childitem 到 get-content 的管道,而是将从 get-childitem 函数检索到的项目放入一个变量中,然后 get-content 函数可以搜索该变量。效果很好!
$FileToLookAt = (Get-ChildItem -Path C:\Users$env:UserName\ -Recurse -Filter "QA11test.hep") | % { $_.FullName }
$User = $env:UserName
if ($FileToLookAt){
$updated = $false
$addtls = Get-Content ($FileToLookAt) | Foreach-Object {
$_ # send the current line to output
if($_ -match "SSL/TLS User Cipher Suites=DEFAULT"){
"IP Port=2023"
"Security Option=2"
$updated = $true
}
}
if ($updated) {
$addtls | Set-Content -Path C:\Users$env:UserName\Desktop\QA11TestSecure.hep
$Message = "Host Explorer updated.`nPlease ensure there is a gold LOCK icon at the bottom left `nof the host explorer window.`nIf not, please contact the help center. Thank you."
} else {
$message = "File was not updated.`nPlease contant the help center immediatly."
}
} else {
$Message = "QA11test.hep not found.`nPlease contact the helpdesk immediately."
}
Msg $env:UserName $Message
exit
我正在尝试检索已知文件名的未知文件路径,然后对该文件名执行 Get-Content
以便我可以对其进行修改。我知道该文件将在 C:\Users$env:UserName\
中,但就我所能及的范围而言(最终用户可能会将其放在更远的地方,例如文档或桌面或其他地方)。
它似乎可以执行 Get-ChildItem
或 Get-Content
,但由于某些原因我不能在同一个脚本中同时执行这两项操作。
总体目标:将 Get-ChildItem 的结果通过管道传递给 Get-Contents 函数,以便我可以修改文件。
这是我的代码:
(Get-ChildItem -Path C:\Users$env:UserName -Filter QA11test.hep) |
Foreach-Object {
$_ # send the current line to output
if($_ -match "SSL/TLS User Cipher Suites=DEFAULT"){
"IP Port=2023"
"Security Option=2"
$Message = "Your host explorer session has been updated."
Msg $env:UserName $Message
exit
} else {
$Message = "Script Failed."
Msg $env:UserName $Message
exit
}
} | Set-Content C:\Users$env:UserName\Telnet\QA11TestSecure.hep
需要帮助!谢谢!
对于如何获取文件及其内容,然后检查文件内容中的任意行,似乎存在一些困惑。我建议不要将其写在大型复合命令中,而是将其分解为不同的样式,以便最大程度地减少管道混乱。有多种方法可以完成相同的任务,有些方法比其他方法更容易遵循,尤其是在调试时。
$fileoutput = @'
IP Port=2023
Security Option=2
'@
$FileToLookAt = Get-ChildItem -Path C:\Users$env:UserName -Recurse -Filter "QA11test.hep" | Get-Content
if ($FileToLookAt)
{
$found = ""
$found = $FileToLookAt | Where-Object {$_ -eq 'SSL/TLS User Cipher Suites=DEFAULT'}
if ($found)
{
$Message = "Your host explorer session has been updated."
Set-Content -Path C:\Users$env:UserName\Telnet\QA11TestSecure.hep -Value $fileoutput -Force
} else
{
$Message = "Script Failed."
}
} else
{
$Message = "QA11test.hep not found."
}
Msg $env:UserName $Message
编辑:好的,确实应该检查 Set-Content 以确保 file/path 存在。假设是这样,这样的事情应该可行。
在最简单的情况下,您需要做的就是使用 Get-Content
命令插入一个管道段:
Get-ChildItem -Path C:\Users$env:UserName -Filter QA11test.hep |
Get-Content | # Send the lines of the input file(s) one by one to ForEach-Object
ForEach-Object { ...
但是,您的方法存在问题:
如果找到文件,则无条件写入输出文件 - 即使未对输入内容进行任何修改。
- 此外,由于代码中的
exit
语句,任何剩余的输入行都从输出文件中省略。
- 此外,由于代码中的
如果找到 no 文件,输出文件要么被创建为一个空文件(
0
字节),要么,如果它已经存在, 替换为一个空文件。
相反,我建议使用 一种基于 switch
statement 的方法,它更快、更简洁、更灵活:
值得注意的是,此解决方案仅在找到输入文件时创建/替换输出文件并且对其进行了修改。
Get-ChildItem -Path C:\Users$env:UserName -Filter QA11test.hep | ForEach-Object {
$updated = $false
$newLines = switch -File $_.FullName -Regex { # Loop over all file lines
'SSL/TLS User Cipher Suites=DEFAULT' {
$_, "IP Port=2023", "Security Option=2" # send 2 additional lines
$updated = $true
}
default { $_ } # pass other lines through
}
# Rewrite the file only if modifications were made.
if ($updated) { $newLines | Set-Content C:\Users$env:UserName\Telnet\QA11TestSecure.hep }
# Emit the appropriate status message.
Msg $env:UserName ('Nothing to update.', 'Your host explorer session has been updated.')[$updated]
}
注意:如果您还需要知道是否找到了输入文件 - 无论是否需要更新 - 设置 $found = $true
在脚本块内并在命令后检查它:if (-not $found) { Msg $env:UserName 'QA11test.hep not found' }
switch -File $_.FullName -Regex
逐行读取输入文件,并根据正则表达式条件匹配每一行:- 如果正则表达式匹配,则输出原始行 (
$_
),以及 2 条附加行;另外,设置标志$updated
以指示内容已修改。 - 所有其他行(
default
条件行)按原样输出。
- 如果正则表达式匹配,则输出原始行 (
$newLines = ...
捕获数组中的(可能修改的)行。- 请注意,这意味着所有行都一次存储在内存中,但文本文件通常不是问题。
只有设置了
$updated
才会写入输出文件(Set-Content
)。最后,
Msg
命令被调用并带有状态适当的消息。- 注意
('msg1', 'msg2')[$updated]
表达式,它是根据标志选择两个值之一的快捷方式:如果$updated
是$true
,则$true
被强制为数组索引1
,因此选择'msg2'
;如果是$false
,索引是0
,选择'msg1'
。
- 注意
谢谢大家的帮助!
(@mklement0,我将修改它以做一些接近你最后一个 post 所做的事情!这对我很有帮助。)
我从不同的 post 中提取了点点滴滴,这就是我想出的,它可以满足我的需要。
此 PowerShell 脚本获取已知文件的完整路径,"QA11test.hep" 并将其加载到一个变量中供以后使用。然后它会在该文件的内容中搜索特定字符串 "SSL/TLS..etc",如果找到它,它会在找到的行下方添加两行,"Port=2023" 和 "Security Option 2"。然后它获取该新文件并将其添加到 C:\Users\$env:UserName\Desktop\QA11TestSecure.hep 而不更改原始 QA11test.hep 文件。因此,它不是从 get-childitem 到 get-content 的管道,而是将从 get-childitem 函数检索到的项目放入一个变量中,然后 get-content 函数可以搜索该变量。效果很好!
$FileToLookAt = (Get-ChildItem -Path C:\Users$env:UserName\ -Recurse -Filter "QA11test.hep") | % { $_.FullName }
$User = $env:UserName
if ($FileToLookAt){
$updated = $false
$addtls = Get-Content ($FileToLookAt) | Foreach-Object {
$_ # send the current line to output
if($_ -match "SSL/TLS User Cipher Suites=DEFAULT"){
"IP Port=2023"
"Security Option=2"
$updated = $true
}
}
if ($updated) {
$addtls | Set-Content -Path C:\Users$env:UserName\Desktop\QA11TestSecure.hep
$Message = "Host Explorer updated.`nPlease ensure there is a gold LOCK icon at the bottom left `nof the host explorer window.`nIf not, please contact the help center. Thank you."
} else {
$message = "File was not updated.`nPlease contant the help center immediatly."
}
} else {
$Message = "QA11test.hep not found.`nPlease contact the helpdesk immediately."
}
Msg $env:UserName $Message
exit