Kevin
Kevin

Reputation: 193

Forming your Array in a foreach loop and return that array

I have for now a fixed list of items that need to be "backuped" and afterwards played back to their origin path.

It has to be done "complex" so

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

isn't allowed

I was thinking about to achive this with a "list of items" that is either aquired through a csv-import or a pre determind arraylist.

But i'm stuck with the part to get stuff back to their origin place while achiving this.

code actually looks like this atm.

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

This explains how I was thinking about it. But I made it to complex for my Brain to get it done properly atm. And I can't figure out how to solve this mess now.

I don't need you to do my work tho. I'm just searching for any kind of help to get my mess readable again or better said correct and understandable.

Sry for the big mess here.

Edit 1:

Playing around with the "Get-Something" as mentiond in the answers. But either way I'm turning around the puzzle pieces. I won't get any data out of Get-Something my return is null everytime.

Edit 2:

Found out was missing the '-passthru', still searching for the "originpath" how to put it all together.

Edit 3:

As there was mentiond the Custom Object I had a new clue and come to this

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

and as for now where I'm testing this I have errors comming up like this one.

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

Edit 4:

For any reason, I don't know why, it gets fixed if I do it like this.

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

Upvotes: 1

Views: 470

Answers (2)

js2010
js2010

Reputation: 27418

Maybe this will help. Passthru the copies to the $temp to a variable, then you can use that variable to reverse it. Copy-Item can take an array as the source.

$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

Umm, if you had a csv like this:

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

backup would be:

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

restore would be:

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

Upvotes: 1

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200193

The canonical way of doing what you described is this:

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
}

or this (slightly simplified, since PowerShell functions automatically return all non-captured output):

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

Appending to an array in a loop should be avoided for performance reasons, because with every iteration the array would be re-created with the size increased by one, then all existing elements would be copied, and finally the new element would be placed in the additional field.

The array subexpression operator around the foreach loop ensures that $data contains an array, regardless of how many elements the loop produces.

The comma in the return statement prevents PowerShell from unrolling the array upon returning it to the caller. More specifically, it wraps the array $data into a second array, so that PowerShell unrolls only that outer array, leaving the inner array untouched.

Upvotes: 1

Related Questions