public/Add-SkylineFiles.ps1

Function Add-SkylineFiles {
    <#
    .SYNOPSIS
    Uploads multiple files and folders from a local path to a remote site
     
    .DESCRIPTION
    Uploads multiple files and folders from a local path to a remote site
     
    .EXAMPLE
    Add-SkylineFiles -Path C:\dev\app\dist -Folder "Style Library/app" -Includes "*.js", "*.css"
 
    .EXAMPLE
    Add-SkylineFiles -Path C:\dev\app\dist\webparts\widget.html -Folder "Style Library/app/webparts"
 
    .PARAMETER Path
    Local path to folder containing files to upload
 
    .PARAMETER Folder
    Remote site-relative folder to upload files into
 
    .PARAMETER Includes
    Array of wildcard-like strings which are matched against local file paths and included in upload.
    When -Includes is specified, everything else is excluded by default.
 
    Example 1: -Includes "*.js", "*.css"
    Example 2: -Includes "*/dist/js/*"
 
    .PARAMETER Excludes
    Array of wildcard-like strings which are matches against local files paths and excluded from upload.
    When -Excludes is specified with an -Includes, the -Excludes will run after and exclude from the narrowed result set.
 
    Example 1: -Excludes "*/img/*"
    Example 2: -Excludes "*.map*"
 
    .PARAMETER Recurse
    TRUE by default. Will recurively upload any subfolders found in the -Path directory.
    Set -Recurse:$False to disable and only upload the files found in the -Path directory.
 
    .PARAMETER Checkout
    If versioning is enabled, this will check out the file first if it exists, upload the file, then check it in again.
 
    .PARAMETER CheckInComment
    The comment added to the checkin.
 
    .PARAMETER Approve
    Will auto approve the uploaded file.
 
    .PARAMETER ApproveComment
    The comment added to the approval.
 
    .PARAMETER Publish
    Will auto publish the file.
 
    .PARAMETER PublishComment
    The comment added to the publish action.
 
    .PARAMETER UseWebDav
    Use Web Dav for the upload.
 
    .PARAMETER Web
    The web to apply the command to. Omit this parameter to use the current web.
     
    #>

    [cmdletbinding()]   
    param(
        [Parameter(Mandatory = $true)]        
        [string]$Path = '',
        [Parameter(Mandatory = $true)]                
        [string]$Folder = '', 
        [Parameter(Mandatory = $false)]
        [string[]]$Includes = @(),
        [Parameter(Mandatory = $false)]
        [string[]]$Excludes = @(),
        [switch]$Recurse = $true,
        [switch]$Checkout,
        [string]$CheckInComment = '',
        [switch]$Approve,
        [string]$ApproveComment = '',
        [switch]$Publish,
        [string]$PublishComment = '',
        [switch]$UseWebDav,
        [Microsoft.SharePoint.Client.Web]$Web
    )
    
    Process
    {
        Write-Debug ( "Running $($MyInvocation.MyCommand).`n" `
                    + "PSBoundParameters:`n$($PSBoundParameters | Format-List | Out-String)" )

        Try
        {   
            $PSBoundParameters.Remove("Path") | Out-Null
            $PSBoundParameters.Remove("Folder") | Out-Null
            $PSBoundParameters.Remove("Includes") | Out-Null
            $PSBoundParameters.Remove("Excludes") | Out-Null
            $PSBoundParameters.Remove("Recurse") | Out-Null

            $SafePath = (Get-Item $Path).FullName
            $IsPathAFolder = Test-Path -PathType Container -Path $SafePath
            
            Get-ChildItem -Recurse:$Recurse -Path $SafePath | ForEach-Object {
                $File = $PSItem

                # Includes: Skip file if $Includes is not empty and the current filename is not contained in the array
                if ($Includes.Count -gt 0) {
                    $isIncluded = $false
                    $Includes | ForEach-Object { if ($File.FullName -like $_) { $isIncluded = $true; return } }
                    if (!$isIncluded){ return }
                }

                # Excludes: Skip file if $Excludes is not empty and the current filename is contained in the array
                if ($Excludes.Count -gt 0) {
                    $isExcluded = $false
                    $Excludes | ForEach-Object { if ($File.FullName -like $_) { $isExcluded = $true; return } }
                    if ($isExcluded){ return }
                }

                # If -Path is a folder, then persist folder hierarchy when uploading, otherwise for single files use the passed -Folder
                $DestinationSiteDirectory = $Folder
                if ($IsPathAFolder) {
                    $DestinationSiteDirectory += "/" + $File.Directory.FullName.Replace($SafePath,"").Replace("\","/")
                }
                Write-Debug ( "File.Directory.FullName: $($File.Directory.FullName) `n" `
                            + "SafePath: $SafePath `n" `
                            + "DestinationSiteDirectory: $DestinationSiteDirectory" )

                # Upload file to site
                Add-PnPFile -Path $File.FullName -Folder $DestinationSiteDirectory @PSBoundParameters
            }

        }
        Catch
        {
            Throw $_
        }
    }

}