【问题标题】:Forming your Array in a foreach loop and return that array在 foreach 循环中形成您的数组并返回该数组
【发布时间】:2019-08-19 14:19:49
【问题描述】:

我现在有一个需要“备份”并随后播放到其原始路径的项目的固定列表。

它必须做得“复杂”所以

copy from a to b
do some stuff
copy from b to a

不允许

我正在考虑通过“项目列表”来实现这一目标,该“项目列表”可以通过 csv-import 或预先确定的数组列表获取。

但在实现这一目标的同时,我仍然坚持将东西送回原处。

代码实际上看起来像这样。

function Backup-2Temp ($items, $Temp){ 
    foreach ($item in $items){
        Copy-Item -Path $item -Destination "$Temp"
        <#
        Create Array with the filename and originpath
        $pathremind = @(
            += "$itemname" "$originpath"
        )
        #>
    }
    return $pathremind
}
function Restore-Temps($premind,$Temp){
$TempItems = Get-ChildItem -Path $Temp
    foreach($item in $premind){
        |where $item.name -EQ $TempItems.Name
    copy-item -Path "itemTemppath" -Destination $item.originpath
    }
}

$items2copy = @(
    "$testpath\DeviceSettings.ini",
    "$testpath\otc.ini"
)

$user = Read-Host "which User will be reseted"
$Temp = "C:\Users\$user\AppData\Roaming\testTemp"
$testpath = "C:\Users\$user\AppData\Roaming\test"
create-folder -path $Temp
$premind = Backup-2Temp $items2copy $Temp
Remove-Item -Path $testpath -Recurse
Restore-Temps
Remove-Folder $Temp

这解释了我的想法。但我让它变得复杂,让我的大脑在大气压下正确完成它。而且我现在不知道如何解决这个烂摊子。

我不需要你做我的工作。我只是在寻找任何帮助,以使我的混乱再次可读,或者更好地说是正确和易于理解的。

为这里的大混乱感到抱歉。

编辑 1:

玩弄答案中提到的“Get-Something”。但无论哪种方式,我都在转动拼图。我不会从 Get-Something 中获取任何数据,我的返回值每次都是 null。

编辑 2:

发现缺少“-passthru”,仍在寻找“originpath”如何将它们放在一起。

编辑 3:

由于提到了自定义对象,我有了一个新线索并来到了这个

function Backup-2Temps ($myitems){
    foreach($item in $myitems){
        Copy-Item -Path "$item.originpath\$item.name" -Destination $item.Temppath -PassThru
    }
}
function Restore-Temps($myitems){
    foreach($item in $myitems){
        Copy-Item -Path "$item.Temppath\$item.name" -Destination $item.originpath -PassThru
    }
}

$user = Read-Host "which User will be reseted"
$testpath = "C:\Users\$user\AppData\Roaming\test"
$otherpath = "C:\Users\$user\AppData\Roaming\testo"
$p2Temp = "C:\Users\$user\AppData\Roaming"
$Tempn = "testT"

New-Item -Path $p2Temp -Name $Tempn -ItemType "directory"
$Temp = "$p2Temp\$Tempn"

$myitems = @(
[pscustomobject]@{name="Device.txt"; originpath = $testpath; Temppath = $Temp},
[pscustomobject]@{name="otc.txt"; originpath = $testpath; Temppath = $Temp},
[pscustomobject]@{name="test.txt"; originpath = $otherpath; Temppath = $Temp}
)

Backup-2Temps $myitems
Remove-Item -Path $testpath -Force -Recurse
Remove-Item -Path $otherpath -Force -Recurse
New-Item -Path $p2Temp -Name "test" -ItemType "directory"
New-Item -Path $p2Temp -Name "testo" -ItemType "directory"
Restore-Temps $myitems

至于我现在在哪里测试这个,我遇到了像这样的错误。

Copy-Item : "Drive not found. A Drive with the name "@{name=Device.txt; originpath=C" is not found.
In T:\00Scripts\OTC-Copy\OTC-BCK-Complex(Theorie).ps1:8 character:13
+             Copy-Item -Path "$item.Temppath\$item.name" -Destination  ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (@{name=Device.txt; originpath=C:String) [Copy-Item], DriveNotFoundException
    + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.CopyItemCommand

编辑 4:

不知道为什么,如果我这样做,它会得到修复。

foreach($item in $myitems){
    $x = $item.originpath
    $y = $item.name
    Copy-Item -Path "$x\$y" -Destination $item.Temppath -PassThru
}

【问题讨论】:

  • foreach 存储输出对象的最简单方法是将变量分配给foreach 循环。你可以像$var = foreach ($something in $somethingelse) { $obj }一样这样做。

标签: arrays powershell foreach


【解决方案1】:

你描述的典型做法是这样的:

function Get-Something {
    $data = @(foreach (...) {
        # ...
        # do stuff
        # ...
        # then create custom objects with the desired information
        New-Object -Type PSObject -Property @{
            'Itemname'   = ...
            'Originpath' = ...
            'Temppath'   = ...
        }
    })
    return ,$data
}

或者这个(稍微简化,因为 PowerShell 函数会自动返回所有未捕获的输出):

function Get-Something {
    ,@(foreach (...) {
        # ...
        # do stuff
        # ...
        # then create custom objects with the desired information
        New-Object -Type PSObject -Property @{
            'Itemname'   = ...
            'Originpath' = ...
            'Temppath'   = ...
        }
    })
}

出于性能原因,应避免在循环中附加到数组,因为每次迭代都会重新创建数组,大小增加一,然后复制所有现有元素,最后将新元素放置在附加字段中。

foreach 循环周围的数组子表达式运算符确保$data 包含一个数组,无论循环产生多少元素。

return 语句中的逗号可防止 PowerShell 在将数组返回给调用者时展开该数组。更具体地说,它将数组 $data 包装到第二个数组中,以便 PowerShell 仅展开该外部数组,而保持内部数组不变。

【讨论】:

  • 我知道这样做的方式。但是 copy-item 看起来没有输出,或者我错过了什么,因为我没有从我的函数中获取任何数据
  • @Kevin 只需在循环中输出您需要的任何内容。如果Copy-Item 没有产生您需要的输出,您必须自己创建它。
  • 这是我目前的症结所在。也许我正在努力获得像 Itemname Originpath Temppath 这样的“完美输出”。我对自己的想法有点困惑,但感谢您的帮助
  • @Kevin 使用所需信息构建自定义对象:[PSCustomObject]@{'Itemname'=...; 'Originpath'=...; ...}
【解决方案2】:

也许这会有所帮助。将 $temp 的副本传递给一个变量,然后您可以使用该变量来反转它。 Copy-Item 可以以数组为源。

$items2copy = Echo file1 file2
$temp = 'temp'
$originpath = '.'
Mkdir temp
Echo hi | Set-Content file1,file2

$pathremind = Copy-Item $items2copy $temp -PassThru # backup

Copy-Item $pathremind $originpath                   # restore

嗯,如果你有这样的 csv:

item,originpath,temp
file1,.,temp
file2,.,temp

备份将是:

$a = import-csv backups.csv
$a | foreach { $item,$originpath,$temp = $_.item,$_.originpath,$_.temp 
cp $originpath/$item $temp } 

恢复将是:

$a = import-csv backups.csv
$a | foreach { $item,$originpath,$temp = $_.item,$_.originpath,$_.temp
cp $temp/$item $originpath } 

【讨论】:

  • 这不是将所有内容复制到任何地方吗?如果有不同的路径,这将不起作用还是我错了?
  • 确实如此。它不记得多个 originpath 的。我没有从你的问题中明白这一点。
  • 没问题,我并不清楚。但仍然感谢您的意见,仍然从中学到了一些东西。
猜你喜欢
  • 2020-11-14
  • 2018-10-08
  • 2015-04-22
  • 1970-01-01
  • 1970-01-01
  • 2014-12-19
  • 1970-01-01
  • 2020-10-13
  • 1970-01-01
相关资源
最近更新 更多