Link to home
Start Free TrialLog in
Avatar of webdude2000
webdude2000

asked on

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
Avatar of Jian An Lim
Jian An Lim
Flag of Australia image

i think you just need to change your if statement

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

then every folder will move except permanent
Avatar of webdude2000
webdude2000

ASKER

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"
            }
    }
On further testing, it is having issues with deeper subdirectories
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)
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.
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.
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
ASKER CERTIFIED SOLUTION
Avatar of Jian An Lim
Jian An Lim
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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
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.
I agree that is your answer, but i think I have help on your journey to your scripts that work.
Core component of the script provided.
Thank you for the assistance.