Move multiple windows files and folders to specific subfolder using powershell

Unfortunately I am short on time for this client change and so asking this forum:

Initially the request was to organise the clients many folders.
They are an accounting firm so have many client folders and under each, other folders such as 2010, 2011, 2013, marketing etc.
They wanted most of the subfolders folders moved for each client to a folder under each client call Historical.
They also wanted a set of new folders created under each client folder.
These requirements, I had mostly sorted out with PS script.

The problem now is they have additional folders under some clients created by staff that could be anything and files in the root of the client folder.

So the request is now to move everything in the client folder using a wildcard to the client sub folder called historical but exclude the folder called Permanent. I have not figured out how to do this.

So client looks like this on the server for example:

s:\client1\files.doc/xls/pdf etc.
s:\client1\2010
s:\client1\2011
s:\client1\2012
s:\client1\2013
s:\client1\marketing
s:\client1\finplan
s:\client1\business
s:\client1\other-unknown-folders
s:\client1\Permanent

All folders have files within them which have to move as well.

Now:
Will create folder under each client called Historical (Will create the other folders after the move)

So the client folders should be moved and look like:

s:\client1\historical\files.doc/xls/pdf etc.
s:\client1\historical\2010
s:\client1\historical\2011
s:\client1\historical\2012
s:\client1\historical\2013
s:\client1\historical\marketing
s:\client1\historical\finplan
s:\client1\historical\business
s:\client1\historical\other-unknown-folders
s:\client1\Permanent

s:\client2 -- same as above and for all other client under the main drive

I wonder if my copy script could be easily modified to achieve the above?

$srcPath = "c:\test\folder\"
$dstPath = "c:\test\folder\NewLoc"
$clients = get-childitem -path $srcPath  | ? { $_.PSIsContainer} | Select-Object Name

$log = "";

foreach ($client in $clients)
{
      $srcCltPath = $srcPath + "\" + $client.name
      $dstCltPath = $dstPath + "\" + $client.name
      New-Item $dstCltPath -ItemType Directory -Force
      $subFolders = get-childitem $srcCltPath | ? { $_.PSIsContainer} | Select-Object Name      
      
      $log += "New-Item " + $dstCltPath + " -ItemType Directory -Force `r`n"
            
      foreach ($folder in $subFolders){
            $copySrc = $srcCltPath + "\" + $folder.name            
            if ($folder.name -match "2010" -or $folder.name -match "2011"){                  
                  $copyDst = $dstPath + "\" + $client.name + "\historical\" + $folder.name                  
                  Copy-Item $copySrc -destination $copyDst -Recurse
                  
                  $log += "Copy-Item " + $copySrc + " -destination" + $copyDst + " -recurse `r`n"
            }
      }  
}
$log > c:\test\log10.csv
webdude2000Asked:
Who is Participating?
 
Jian An LimSolutions ArchitectCommented:
Move-Item -Path "$ClientLocation\$ClientName\$FolderToMove"  -Destination "$ClientLocation\$ClientName\Historical" -force

the reason is because the file has been created.
0
 
Jian An LimSolutions ArchitectCommented:
i think you just need to change your if statement

if ($folder.name -notmatch "Permanent")

then every folder will move except permanent
0
 
webdude2000Author Commented:
This works:

$ClientLocation = 'C:\Test\folder'
$Clients = Get-ChildItem $ClientLocation

foreach ($Client in $Clients) {
    $ClientName = $Client.Name
    $FoldersToMove = Get-ChildItem "$ClientLocation\$ClientName" | Where-Object {$_.Name -notlike 'Historical' -and $_.Name -notlike 'Permanent'}
    foreach ($FolderToMove in $FoldersToMove) {
       
        $Destination1 = "$ClientLocation\$ClientName\Historical"

        New-Item -Name $FolderToMove -Path $Destination1 -ItemType Directory
        $Destination2 = "$ClientLocation\$ClientName\Historical\$FolderToMove"
        Get-ChildItem -Path "$ClientLocation\$ClientName\$FolderToMove" -Recurse | Move-Item -Destination $Destination2
        Remove-Item -Path "$ClientLocation\$ClientName\$FolderToMove"
            }
    }
0
WEBINAR: 10 Easy Ways to Lose a Password

Join us on June 27th at 8 am PDT to learn about the methods that hackers use to lift real, working credentials from even the most security-savvy employees. We'll cover the importance of multi-factor authentication and how these solutions can better protect your business!

 
webdude2000Author Commented:
On further testing, it is having issues with deeper subdirectories
0
 
Jian An LimSolutions ArchitectCommented:
yes, i think the command should be

Move-Item -Path "$ClientLocation\$ClientName\$FolderToMove"  -Destination $Destination2

(no recursive as this will put everything into the flat structure)

p/s: i haven't do a code testing, but i guess that's your problem when i look at your code, (a wild guess)
can you tell me what is your issue? (without me go into a lab test)
0
 
webdude2000Author Commented:
As it stands without your change it moves the client subfolders and root files under each client as well as the next subfolder correctly yo the historical folder and leaves the permanant folder alone. However folders deeper than that are pulled up and placed in the 2nd subfolder level and files under those are pulled up and directories are created with the file names.

So I had documents called new document.txt and it created a folder called new document.txt

The copy command of my first script worked perfectly however I need to move the items using a wildcard excluding historical and permanent including all files and subdirectories and the directory structured under each main client folder needs to be retained.
0
 
Jian An LimSolutions ArchitectCommented:
for the sack of testing, i have redeveloped this and the correct command should be  ## TESTING at your own risk again##

Move-Item -Path "$ClientLocation\$ClientName\$FolderToMove"  -Destination "$ClientLocation\$ClientName\Historical"

you also don't require to remove the folder [ remove-Item -Path "$ClientLocation\$ClientName\$FolderToMove"] as this is move command.
0
 
webdude2000Author Commented:
Thanks, I will change to your move command. We added the remove command because it was keeping the top level sub folder still in the source location even though we were doing a move.

Seeing this when running the script:

  + CategoryInfo          : WriteError: (C:\Test\folder\...ocument2010.txt:DirectoryInfo) [Move-Item], IOException
    + FullyQualifiedErrorId : MoveDirectoryItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand
 
Move-Item : Cannot create a file when that file already exists.
At C:\Users\ms\Documents\Clients\client\new-move-script.ps1:13 char:84
+ ... ve" -Recurse | Move-Item -Destination $Destination2
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : WriteError: (C:\Test\folder\...ocument2010.txt:FileInfo) [Move-Item], IOException
    + FullyQualifiedErrorId : MoveFileInfoItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand
0
 
webdude2000Author Commented:
Seems to work now:
It throws up errors because I did not define Directory anymore behind –Itemtype.
I had to leave –ItemType in otherwise the script does not work and if I state directory then it moves files from the client root folder but also creates directories of the same name, now it complains but moves both files and folders.

$ClientLocation = 'C:\Test\folder'
$Clients = Get-ChildItem $ClientLocation

foreach ($Client in $Clients) {
    $ClientName = $Client.Name
    $FoldersToMove = Get-ChildItem "$ClientLocation\$ClientName" | Where-Object {$_.Name -notlike 'Historical' -and $_.Name -notlike 'Permanent'}
    foreach ($FolderToMove in $FoldersToMove) {
       
        $Destination1 = "$ClientLocation\$ClientName\Historical"

        New-Item -Name $FolderToMove -Path $Destination1 -ItemType
        $Destination2 = "$ClientLocation\$ClientName\Historical\$FolderToMove"
        Get-ChildItem -Path "$ClientLocation\$ClientName\$FolderToMove" -Recurse
    Move-Item -Path "$ClientLocation\$ClientName\$FolderToMove" -Destination "$ClientLocation\$ClientName\Historical" -force



        $log += "Move-Item " + $FoldersToMove + " -destination" + $Destination2 + " -recurse `r`n"
            }
    }


    $log > c:\test\log20.csv
0
 
webdude2000Author Commented:
I've requested that this question be closed as follows:

Accepted answer: 0 points for webdude2000's comment #a40757613

for the following reason:

PS scripts that works.
0
 
Jian An LimSolutions ArchitectCommented:
I agree that is your answer, but i think I have help on your journey to your scripts that work.
0
 
webdude2000Author Commented:
Core component of the script provided.
Thank you for the assistance.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.