2

I have the below script which is working fine for what we need thus far however running into an error as the file names have changed.

With the below script it is providing a Cannot Find Path error as the filenames have changed. Where am i going wrong with this one?

## Add ShareFile PowerShell Snap-in
Add-PSSnapin ShareFile

## Create new authentiation file
#New-SfClient -Name "C:\Sharefile\SVCACC.sfps" -Account midl

## Variables ##
$OutputAppReqFID = "fo4a3b58-bdd6-44c8-ba11-763e211c183f"
$Project = 'M000'
$LocalPath = "\\file.server.au\$project\DATA\DATA CUSTODIAN\OUTPUT\"
$sfClient = Get-SfClient -Name C:\sharefile\SVCACC.sfps
$OutputAppReqFID_URL = (Send-SfRequest $sfClient -Entity Items -id $OutputAppReqFID).Url


## Create PS Drive ##
New-PSDrive -Name "sfDrive-$($project)" -PSProvider ShareFile -Client $sfClient -Root "\" -RootUri $OutputAppReqFID_URL

## Copy all files from folders to ShareFile
foreach ($file in Get-ChildItem -Path $LocalPath -Recurse -Force | Where-Object {$_.Mode -ne "d-----"} | Select FullName -ExpandProperty FullName) { 
     Get-ChildItem $file  -Recurse | Rename-Item -NewName { $_.Directory.Name+'_'+$_.Name}
     Copy-SfItem -Path $file -Destination "sfDrive-$($project):" 
    #remove-item $file
    }

<## Remove all folders from UNC directory
foreach ($folder in Get-childitem -Path $LocalPath -Recurse | Where-Object {$_.Mode -eq "d-----"} | Select-Object -ExpandProperty FullName) {
    remove-item $folder
    }
    #>

## Remove PS Drive ##
Remove-PSDrive "sfdrive-$($project)"

Error recieved is below:

Copy-SfItem : Cannot find path '\\file.server.au\M000\DATA\DATA CUSTODIAN\OUTPUT\New Text Document.txt' because it does not exist.
At line:43 char:6
+      Copy-SfItem -Path $file -Destination "sfDrive-$($project):"
+      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (\\file.serve...xt Document.txt:String) [Copy-SfItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,ShareFile.Api.Powershell.CopySfItem

1 Answers1

1

The problem is that you are renaming $file and then trying to Copy-SfItem -Path $file in the very next line. This reference to $file is still pointing to the old name before the rename. You need to instead capture the path to the newly renamed filepath and then reference that in your Copy-SfItem command

foreach ($file in Get-ChildItem -Path $LocalPath -Recurse -Force | 
        Where-Object { $_.Mode -ne 'd-----' } | 
            Select-Object -ExpandProperty FullName) {
                
    # capture reference to the new file name by using -PassThru switch with 
    # the Rename-Item cmdlet and saving in a variable ($renamedFile) 
    $renamedFile = Get-ChildItem $file -Recurse | 
        Rename-Item -NewName { $_.Directory.Name + '_' + $_.Name } -PassThru

    # Now we copy using our $newFile reference
    Copy-SfItem -Path $renamedFile -Destination "sfDrive-$($project):" 

    # followed by removing the file if needed
    # remove-item $renamedFile
}

This can be cleaned up some as well.

  • Adding the -File switch to Get-ChildItem will give us only files removing the need for | Where-Object {$_.Mode -ne "d-----"}
  • Taking off the | Select-Object -ExpandProperty FullName from the end of the foreach will eliminate the need to calling Get-ChildItem again in the first foreach loop.
foreach ($file in Get-ChildItem -Path $LocalPath -Recurse -Force -File ) {

    # capture reference to the new file name by using -PassThru switch with 
    # the Rename-Item cmdlet and saving in a variable ($newFile) 
    $renamedFile = $file | Rename-Item -NewName { $_.Directory.Name + '_' + $_.Name } -PassThru

    # Now we copy using our $newFile reference
    Copy-SfItem -Path $renamedFile -Destination "sfDrive-$($project):" 

    # followed by removing the file if needed
    # remove-item $renamedFile
}

Updates based on your comments

foreach ($file in Get-ChildItem -Path $LocalPath -Recurse -Force -File ) {

    $file = if ($file.Directory.FullName -ne $LocalPath) {
        # capture reference to the new file name by using -PassThru switch with 
        # the Rename-Item cmdlet and saving in a variable ($file) 
        $file | Rename-Item -NewName { $_.Directory.Name + '_' + $_.Name } -PassThru
    }
    else {
        #Pass thru $file with no changes
        $file
    }

    # Now we copy using our $file reference
    Copy-SfItem -Path $file -Destination "sfDrive-$($project):" 

    # followed by removing the file if needed
    # remove-item $file
}
Daniel
  • 4,792
  • 2
  • 7
  • 20
  • Thanks Daniel, This has bit the nail on the head so to speak which is awesome and much appreciated. I have learnt another thing which is awesome! One of the other things that i now need to correct is if the file is in the OUTPUT folder so in other words anything in the root directory need to NOT be renamed. i take it i need to add an if statement on this which would like something similar to this if ($file.FullName eq "//UNCpath/OUTPUT") { do nothing } else { run rename script} – Andrew Waters Sep 28 '21 at 03:46
  • You're welcome @AndrewWaters. Have a look at my update to show how to conditionally rename the file based on whether the file is in the root directory or not. – Daniel Sep 28 '21 at 05:38
  • Hey @Daniel, Thanks again, i was very close with what i had to get it to work. I applied your modifications above, however it still seems to be renaming anything in the /OUTPUT directory I should confirm the directories im testing with //file.server.au/m000/data/data custodian/output (Root) this should be the only folder that wont rename files. Every folder within should rename – Andrew Waters Sep 28 '21 at 05:53
  • Try removing the `'\'` from the end of `$LocalPath = "\\file.server.au\$project\DATA\DATA CUSTODIAN\OUTPUT\"` – Daniel Sep 28 '21 at 13:41
  • That has hit the spot on the head! When a folder is created inside a folder e.g folder1/folder2/file.txt it doesnt rename Folder1_Folder_2_file.txt any ideas. i have been looking at it for a few hours and i dont seem to be getting any where – Andrew Waters Sep 29 '21 at 03:50
  • Try this `$file | Rename-Item -NewName { ($_.Directory.FullName -replace [regex]::Escape($LocalPath) -split '\\' -notmatch '^ *$' -join '_') + "_" + $_.Name } -PassThru` – Daniel Sep 29 '21 at 05:09