将多个“ForEach”语句分层以遍历目录并对找到的每个文件执行操作

时间:2014-04-28 18:00:37

标签: powershell sharepoint csv

我一直在为这个Powershell脚本工作一周,它几乎按预期工作。

本质上,脚本到达指定目录,我们有另一个脚本将.CSV文件放入,抓取.CSV文件并将找到的信息推送到Sharepoint列表中,好吧,无论如何都是这样。如果我手动指定文件,我已经让脚本完美地运行了,我遇到的问题实际上是将所有.CSV文件放入一个组中,然后循环遍历每个.CSV以将信息拉出并将其推送到分享点列表。完成后,它会将文件从.CSV重命名为.ARCHIVED,以便其他脚本进入并在完成后重新定位。

我想我已经通过选择性(创造性)故障排除找出了我做错了什么,我只是在确定问题后不知道如何继续。

我声明字符串$ Filecsv如下:

$Filecsv = get-childitem "Z:\" -recurse | where {$_.extension -eq ".csv"} 

因此,这会进入我的'Z:\'目录,并将所有带有.CSV扩展名的文件拉出来并将它们组合成一个表...

ForEach ($items in $Filecsv) {

这说明每个项目,执行逻辑......

foreach($row in $Filecsv)

唯一的问题是,当我调用$ Filecsv时,它会返回目录中每个.CSV文件的列表,如下所示:

enter image description here

因此,当我执行“将信息放入我的列表”的代码时,只有文件名被添加到我的Sharepoint列表中....

enter image description here

现在,我可以看到这里发生了什么,它从$ Filecsv表中拉出'Name',并将其推送到Sharepoint,但是,我不知道如何重新构建我的逻辑以便它可以像预期因为它现在存在,它应该(对我而言)工作,因为我认为它,但我仍然是Sharepoint的新手,我肯定在这里遗漏了一些东西。

下面是完整代码,如果它有帮助:

# Add SharePoint PowerShell Snapin which adds SharePoint specific cmdlets 
Add-PSSnapin Microsoft.SharePoint.PowerShell -EA SilentlyContinue

#start the counter at 1 to track times script has looped
$iterations = 1

# set the location where the .CSV files will be pulled from and define the 
# file extension we are concerned with 
$filecsv = get-childitem "Z:\" -recurse | where {$_.extension -eq ".csv"} 

# for each file found in the directory
ForEach ($items in $Filecsv) {

# check to see if files exist, if not exit cleanly 
if ($Filecsv) {"File exists" + $Filecsv} else {exit}

# count the times we've looped through
"Iterations : $iterations"

# specify variables needed.  The webURL should be the site URL, not including the list
# the listName should be the list name
$WebURL = "http://SHAREPOINTURL/"
$listName = "test"

# Get the SPWeb object and save it to a variable
$web = Get-SPWeb -identity $WebURL
# Get the SPList object to retrieve the list
$list = $web.Lists[$listName]

# START deletes all items. code shows the number of items in a list, then deletes all items  
# If you don't want your script to delete items, then remove this
$site = new-object Microsoft.SharePoint.SPSite ( $WebURL ) 
$web = $site.OpenWeb() 
"Web is : " + $web.Title 

# Enter name of the List below instead of 
$oList = $web.Lists["test"]; 
"List is :" + $oList.Title 
"List Item Count: " + $oList.ItemCount 

#delete existing contents and replace with new stuff
$collListItems = $oList.Items; 
$count = $collListItems.Count - 1 
for($intIndex = $count; $intIndex -gt -1; $intIndex--) {         
"Deleting record: " + $intIndex         
$collListItems.Delete($intIndex); 
}

# END Deletes all items



# goes through the CSV file and performs action for each row
foreach($row in $Filecsv)
{
      $newItem = $list.items.Add()
      $item = $list.items.add()      
      # Check if cell value is not null in excel
      if ($row."Name" -ne $null)
            # Add item to sharepoint list.  for this one, I had to use the internal column name. 
            #You don't always have to, but I had trouble with one SharePoint column, so I did
            {$newItem["Name"] = $row."Name"}
                else{$newItem["Name"] = $row."Not Provided"}


      if ($row."Description" -ne $null)
            {$newItem["Description"] = $row."Description"}  
                else{$newItem["Description"] = $row."No Description"}

      if ($row."NetworkID" -ne $null)
            {$newItem["Network ID"] = $row."NetworkID"}  
                else{$newItem["Network ID"] = $row."No NetworkID"}
      if ($row."Nested" -ne $null)
            {$newItem["Nested"] = $row."Nested"} 
                else{$newItem["Nested"] = $row."Not Nested"}

# Commit the update, then loop again until end of file 

$newItem.Update()
}

# get the date and time from the system

$datetime = get-date -f MMddyy-hhmmtt

# rename the file 
$NewName = $items.fullname -replace ".csv$","$datetime.csv.archived"

$Items.MoveTo($NewName)

# +1 the counter to count the number of files we've looped through
$iterations ++
}

2 个答案:

答案 0 :(得分:2)

一个非常粗略的外观表明你需要在主循环中使用$ items而不是$ filecsv。

基本上你是循环遍历$ filecsv集合的内容,所以你需要查看$ items。

答案 1 :(得分:1)

您的ForEach循环看起来是多余的,因为它们都循环遍历FileInfo对象列表。我想你想找到所有文件,并为每个文件加载到内存中并处理它的内容。我们将走那条路。

我已将SharePoint对象创建移出循环,因为我没有看到为处理的每个文件反复创建对象的任何意义,因为它从未根据文件引用任何内容或它内容。它简单地使同一个对象重叠,结束和结束。

# Add SharePoint PowerShell Snapin which adds SharePoint specific cmdlets 
Add-PSSnapin Microsoft.SharePoint.PowerShell -EA SilentlyContinue

#start the counter at 1 to track times script has looped
$iterations = 1

# specify variables needed.  The webURL should be the site URL, not including the list
# the listName should be the list name
#Setup SP object
$WebURL = "http://SHAREPOINTURL/"
$listName = "test"

# Get the SPWeb object and save it to a variable
$web = Get-SPWeb -identity $WebURL
# Get the SPList object to retrieve the list
$list = $web.Lists[$listName]

# START deletes all items. code shows the number of items in a list, then deletes all items  
# If you don't want your script to delete items, then remove this
$site = new-object Microsoft.SharePoint.SPSite ( $WebURL ) 
$web = $site.OpenWeb() 
"Web is : " + $web.Title 

# Enter name of the List below instead of 
$oList = $web.Lists["test"]; 
"List is : " + $oList.Title 
"List Item Count: " + $oList.ItemCount 

#delete existing contents and replace with new stuff
$collListItems = $oList.Items; 
$count = $collListItems.Count - 1 
for($intIndex = $count; $intIndex -gt -1; $intIndex--) {         
"Deleting record: " + $intIndex         
$collListItems.Delete($intIndex); 
}

# END Deletes all items

找到所有CSV文件,然后开始循环浏览它们的列表。我删除了检查以查看文件是否存在。你只需要一个目录列表来查找这些文件,它们确实应该存在。

# set the location where the .CSV files will be pulled from and define the 
# file extension we are concerned with 
$CSVList = get-childitem "Z:\" -recurse | where {$_.extension -eq ".csv"} 
ForEach ($CSVFile in $CSVList) {

# count the times we've looped through
"Iterations : $iterations"

现在,这是不同的。它加载CSV文件,并将其中的每一行作为$ row处理。我很确定这是你从一开始就打算做的。我还将它从If(Something -ne $ null)更改为检查null或为空,因为其中任何一个都可以存在,而后者可能会导致一些问题。它通常只是一种更安全的方法。

foreach($row in (Import-CSV $CSVFile.FullName))
{
      $newItem = $list.items.Add()
      $item = $list.items.add()      
      # Check if cell value is not null in excel
      if (![string]::IsNullOrEmpty($row."Name"))
            # Add item to sharepoint list.  for this one, I had to use the internal column name. 
            #You don't always have to, but I had trouble with one SharePoint column, so I did
            {$newItem["Name"] = $row."Name"}
                else{$newItem["Name"] = $row."Not Provided"}

      if (![string]::IsNullOrEmpty($row."Description"))
            {$newItem["Description"] = $row."Description"}  
                else{$newItem["Description"] = $row."No Description"}

      if (![string]::IsNullOrEmpty($row."NetworkID"))
            {$newItem["Network ID"] = $row."NetworkID"}  
                else{$newItem["Network ID"] = $row."No NetworkID"}
      if (![string]::IsNullOrEmpty($row."Nested"))
            {$newItem["Nested"] = $row."Nested"} 
                else{$newItem["Nested"] = $row."Not Nested"}

# Commit the update, then loop again until end of file 

$newItem.Update()
}

我真的不明白你为什么要两次添加一个新项目,但如果它有效,那么你就会有更大的力量。然后你的位重命名文件(嘿,这看起来很熟悉):

# get the date and time from the system

$datetime = get-date -f MMddyy-hhmmtt

# rename the file 
$NewName = $CSVFile.fullname -replace ".csv$","$datetime.csv.archived"

$CSVFile.MoveTo($NewName)

# +1 the counter to count the number of files we've looped through
$iterations ++
}

我确实重命名了一些东西,使它们更能说明它们代表什么($ Items to $ CSVFile,什么不是)。看看这是否适合你。如果您有任何问题或疑虑,请告诉我。

编辑:好的,要修复尝试从当前文件夹中提取每个项目的循环,我们引用它的FullName属性。一行改变了:

foreach($row in (Import-CSV $CSVFile.FullName))