导入CSV并更新特定行

导入CSV并更新特定行,csv,powershell,Csv,Powershell,所以我有一个脚本,在登录时运行,在用户机器上搜索PST,然后将它们复制到等待迁移的等待区。 搜索/复制完成后,它将输出到CSV,如下所示: Hostname,User,Path,Size_in_MB,Creation,Last_Access,Copied COMP1,user1,\\comp1\c$\Test PST.pst,20.58752,08/12/2015,08/12/2015,Client copied COMP1,user1,\\comp1\c$\outlook\outlook.p

所以我有一个脚本,在登录时运行,在用户机器上搜索PST,然后将它们复制到等待迁移的等待区。 搜索/复制完成后,它将输出到CSV,如下所示:

Hostname,User,Path,Size_in_MB,Creation,Last_Access,Copied

COMP1,user1,\\comp1\c$\Test PST.pst,20.58752,08/12/2015,08/12/2015,Client copied
COMP1,user1,\\comp1\c$\outlook\outlook.pst,100,08/12/2015,15,12,2015,In Use
如果复制的状态正在使用中,则同一登录脚本具有导入CSV的IF,并进一步尝试将PST复制到保留区域。如果成功,则将结果导出到CSV文件

我的问题是,有没有办法让它修改现有的CSV或更改拷贝状态?我可以让它在末尾添加新行,但不能更新

这是我的“重试”脚本:

# imports line of csv where PST file is found to be in use
$PST_IN_USE = Import-CSV "\\comp4\TEMPPST\PST\$HOSTNAME - $USER.csv" | where { $_.copied -eq "In Use" }

ForEach ( $PST_USE in $PST_IN_USE )
{ $NAME = Get-ItemProperty $PST_IN_USE.Path | select -ExpandProperty Name
$NEW_NAME = $USER + "_" + $PST_IN_USE.Size_in_MB + "_" + $NAME

# attempts to copy the file to the pst staging area then rename it.
TRY { Copy-Item $PST_IN_USE.Path "\\comp4\TEMPPST\PST\$USER" -ErrorAction SilentlyContinue
Rename-Item "\\comp4\TEMPPST\PST\$USER\$NAME" -NewName $NEW_NAME

# edits the existing csv file replacing "In Use" with "Client Copied"
$PST_IN_USE.Copied -replace "In Use","Client Copied"

} # CLOSES TRY

# silences any errors.
CATCH { }


$PST_IN_USE | Export-Csv "\\comp4\TEMPPST\PST\$HOSTNAME - $USER.csv" -NoClobber -NoTypeInformation -Append


} # CLOSES ForEach ( $PST_USE in $PST_IN_USE )
这是结果CSV

Hostname,User,Path,Size_in_MB,Creation,Last_Access,Copied
COMP1,user1,\\comp1\c$\Test PST.pst,20.58752,08/12/2015,08/12/2015,Client copied
COMP1,user1,\\comp1\c$\outlook\outlook.pst,100,08/12/2015,15,12,2015,In Use
COMP1,user1,\\comp1\c$\outlook\outlook.pst,100,08/12/2015,15,12,2015,Client copied

这几乎可以肯定是非常简单的东西,但如果是的话,这是我在脚本编写中还没有遇到的东西。目前我主要在IF/ELSE土地工作

如果要更改CSV文件,必须重新完全写入,而不仅仅是添加新行。在您的情况下,这意味着:

# Get the data
$data = Import-Csv ...

# Get the 'In Use' entries
$inUse = $data | where Copied -eq 'In Use'

foreach ($x in $inUse) {
   ...
   $x.Copied = 'Client Copied'
}

# Write the file again
$data | Export-Csv ...

这里的要点是,您从CSV中获取所有行,修改您处理的行,然后将完整的集合再次写入文件。

我已经破解了它。几乎可以肯定,这是一种冗长的方式,但它是有效的,而且也相对干净

#imports line of csv where PST file is found to be in use
$PST_IN_USE = Import-CSV "\\comp4\TEMPPST\PST\$HOSTNAME - $USER.csv" | where { $_.copied -eq "In Use" }

$PST_IN_USE | select -ExpandProperty path | foreach { 

# name of pst
$NAME = Get-ItemProperty $_ | select -ExpandProperty Name

# size of pst in MB without decimals
$SIZE = Get-ItemProperty $_ | select -ExpandProperty length | foreach { $_ / 1000000 }

# path of pst
$PATH = $_

# new name of pst when copied to the destination
$NEW_NAME = $USER + "_" + $SIZE + "_" + $NAME

TRY { Copy-Item $_ "\\comp4\TEMPPST\PST\$USER" -ErrorAction SilentlyContinue

      TRY { Rename-Item "\\comp4\TEMPPST\PST\$USER\$NAME" -NewName $NEW_NAME -ErrorAction SilentlyContinue | Out-Null }

      CATCH { $NEW_NAME = "Duplicate exists" }

      $COPIED = "Client copied" }

CATCH { $COPIED = "In use" ; $NEW_NAME = " " }

$NEW_FILE = Test-Path "\\comp4\TEMPPST\PST\$HOSTNAME - $USER 4.csv"

IF ( $NEW_FILE -eq $FALSE )
   { "Hostname,User,Path,Size_in_MB,Creation,Last_Access,Copied,New_Name" | 
     Set-Content "\\lccfp1\TEMPPST\PST\$HOSTNAME - $USER 4.csv" }

"$HOSTNAME,$USER,$PATH,$SIZE,$CREATION,$LASTACCESS,$COPIED,$NEW_NAME" | 
Add-Content "\\comp4\TEMPPST\PST\$HOSTNAME - $USER 4.csv"

} # CLOSES FOREACH #

$a = Import-CSV "\\comp4\TEMPPST\PST\$HOSTNAME - $USER.csv" | where { $_.copied -ne "in use" }
$b = Import-Csv "\\comp4\TEMPPST\PST\$HOSTNAME - $USER 4.csv"

$a + $b | export-csv "\\comp4\TEMPPST\PST\$HOSTNAME - $USER 8.csv" -NoClobber -NoTypeInformation

谢谢你的帮助。有时需要休息片刻,喝一大杯咖啡,才能以不同的方式看待事情。

谢谢乔伊,工作非常愉快*编辑进一步发挥,它不工作,因为我想。如果将多个文件设置为“正在使用”,则在第一次成功时会将它们全部更改为“客户端已复制”。有什么方法可以针对具体的成功?再次感谢