Archive SharePoint Library Files into Sub-Folders using PowerShell
Requirement: We have a large library with more than 20,000 files stored in the root of the document library without any sub-folders. Got to move files into Sub-folders to improve performance.
Solution: We analyzed the library content and decided to move files into sub-folders based on the file’s created date.
Archive Files into Sub-Folders in SharePoint using PowerShell
PowerShell script to move files into sub-folders in SharePoint document library:
#Import PowerShell Snap-in
Add-PSSnapin Microsoft.SharePoint.PowerShell -erroraction SilentlyContinue
#Create a custom function to archive files
Function Archive-Files($WebURL, $ListName)
{
#Get the web and List
$Web = Get-SPWeb $WebURL
$List= $web.Lists[$ListName]
$RootItems = $List.RootFolder.files
Write-host "Total number of files found in the Root: "$RootItems.count
#Move each file in the root folder to archive folder
foreach($item in $RootItems)
{
#Get the File
$file = $Web.GetFile($item.URL)
#Get the Month & Year values from the File's crated date
$MonthYearValue = $file.TimeCreated.ToString('MMM-yyyy')
# Try to Get the Archive Sub-Folder in the target Library
$TargetFolder = $List.ParentWeb.GetFolder($List.RootFolder.Url + "/" +$MonthYearValue);
#If the Archive folder doesn't exist, Create it!
if ($TargetFolder.Exists -eq $false)
{
$TargetFolder = $List.Folders.Add("", [Microsoft.SharePoint.SPFileSystemObjectType]::Folder, $MonthYearValue)
$TargetFolder.Update()
}
#Move the File
$file.MoveTo($TargetFolder.Url + "/" + $File.name)
}
}
#Call the function to Archive Files
Archive-Files "https://sharepoint.crescent.com/sites/marketing/" "Invocies"
This script preserves Metadata, BTW! You can also move files into sub-folders of another SharePoint library for archival.
Move List Items to Sub-Folders using PowerShell:
In another scenario, I had to move List items to Sub-folders. Here is the script:
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
#Variables
$WebURL = "https://portal.crescent.com/News/"
$ListName ="News List"
#Get site object
$Web = Get-SPWeb $WebURL
$List = $Web.Lists[$ListName]
$TargetFolder = $Web.ServerRelativeUrl + "/" + $List.RootFolder.Url + "/"+ "2014/Jan"
#Get all Files Created specific time frame
$Query = '<Where><And><Geq><FieldRef Name="Date" /><Value Type="DateTime">2014-01-01T00:00:00Z</Value></Geq><Leq><FieldRef Name="Date" /><Value Type="DateTime">2014-01-31T00:00:00Z</Value> </Leq> </And> </Where>'
$SPQuery = new-object Microsoft.SharePoint.SPQuery
$SPQuery.ViewAttributes = "Scope='Recursive'" #To include Sub-folders in the library
$SPQuery.Query = $Query
$ItemCollection =$List.GetItems($SPQuery)
Foreach($Item in $ItemCollection)
{
$File=$Web.GetFile($Item.URL)
$TargetPath=$TargetFolder+"/"+$Item.ID.ToString()+"_.000"
$File.MoveTo($TargetPath)
write-host "Moved Item:"$Item.ID
}
Write-host "Total Items Moved:"$ItemCollection.count
Been searching for days now!
This line saved me and my timeline: $file.MoveTo($TargetFolder.Url + “/” + $File.name)
Thank you so much!
Note: you have to have the same library structure to be able to maintain meta-data