导入CSV并更新特定行

时间:2015-12-15 12:17:58

标签: 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.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工作!

2 个答案:

答案 0 :(得分:2)

如果要更改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中获取所有行,修改您处理的那些行,然后再将完整的集合写回文件。

答案 1 :(得分:0)

我已经破解了它。这几乎肯定是一个漫长的方式,但它的工作原理相对干净。

#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

感谢您的帮助。有时需要花一点时间和一大杯咖啡以不同的方式看待事物。