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?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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
webdude2000Author Commented:
On further testing, it is having issues with deeper subdirectories
0
Redefine Your Security with AI & Machine Learning

The implications of AI and machine learning in cyber security are massive and constantly growing, creating both efficiencies and new challenges across the board. Check out our on-demand webinar to learn more about how AI can help your organization!

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
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.