Help My tool to organize files

This topic contains 2 replies, has 2 voices, and was last updated by  Davide Nota 3 weeks, 4 days ago.

  • Author
  • #80375

    Davide Nota

    Hi Powershell followers
    my name is davide i am learning powershell and i am practising creating a tool to organize files in subdirectories

    Actual directory structure multiple files in multiple folders

    Desired Directory structure
    (the _count is added in case of duplicates names) and seems to work

    I used some codes find here and there and trying to put it toghether.
    it seams to work partially
    some file are renamed and moved properly but some remain in the original folder (some renamed and some with original name)

    Here is what i have done so far.
    (feel free to move or format the code as per Good Practice format so i can also learn how shoud be done)

    if you are testing make sure to have a test folder with some test files
    do not use on persolan files as they are renamed and moved
    i dont want you to lose or damage your personal files

    [Reflection.Assembly]::LoadFile('C:\Windows\Microsoft.NET\Framework64\v4.0.30319\System.Drawing.dll') | Out-Null
    Function Select-FolderDialog
        param([string]$Description="Select Folder",[string]$RootFolder="Desktop")
     [System.Reflection.Assembly]::LoadWithPartialName("") |
    #Function to promp guest to select the Working Folder
    $objForm = New-Object System.Windows.Forms.FolderBrowserDialog
            $objForm.Rootfolder = $RootFolder
            $objForm.Description = $Description
            $Show = $objForm.ShowDialog()
            If ($Show -eq "OK")
                Return $objForm.SelectedPath
                Write-Error "Operation cancelled by user."
    $folder = Select-FolderDialog
    #Desired Destination Directory Structure
    $des_path = "$folder\$year\$new_folder_name"
    #get the LastwriteTime to rename the Folders
    $x = $_.LastWriteTime.ToShortDateString()
    #get the Year date to rename the Folders
    $year = Get-Date $x -Format yyyy
    $new_folder_name = Get-Date $x -Format yyyy_MM_dd
    #Trim filename without sequencenumbers
    $TrimmedName= $_.lastwritetime.tostring("yyyyMMdd_hhmmss")
    # Get extension of filename
    $ext= $_.Extension 
    # Get filename without sequencenumber but with extension  
    $FullName= $TrimmedName + $ext 
    # Get the path to be used
    $newpath = Join-Path -Path $des_path -ChildPath $FullName
    # Reset numerator in case trimmed file name is in use
    $num= 1
    Get-ChildItem $folder\*.* -Recurse | ForEach-Object { 
    # Make sure we don't fail the Test-Path because it finds and conflicts with itself
    if(!($NewPath -eq $_.FullName)){
    # If path exists loop untill there is a free sequence number 
        if (Test-Path $newpath) {
             while ((Test-Path $newpath))
           $newpath = Join-Path $des_path ($TrimmedName + "_$num" + $ext)    
           if(!($NewPath -eq $_.FullName)){
    # If path does not exist rename file without a sequence number
    if (test-path $des_path){ 
        Rename-Item $_.Fullname $FullName
        Move-Item $FullName $des_path   
        } else {
        new-item -ItemType directory -Path $des_path
        Rename-Item $_.Fullname $FullName
        Move-Item $FullName $des_path    
  • #80390


    Try this:

    $srcFld = "C:\MyOldFolder"
    $destFld = "C:\MyNewFolder\"
    Get-Childitem $srcFld -Recurse | ? {$_.PSIscontainer -eq $false} | % {
        $newfld = (get-Date $_.LastWriteTime -Format "yyyy_MM_dd") # Gets new destination folder name from file last modified.
        If (!(Test-path "$destFld$newFld")) {New-item -ItemType Directory "$destFld$newFld"} # Created destination folder if it doens't exist.
        $newFName = "$(get-Date $_.LastWriteTime -Format 'yyyyMMdd_hhmms')$($_.Extension)" # Sets the new file name
        # The part below increments the file name if it already exists.
        $i = 0
        While (test-path "$destFld$newFld\$newFName") {
            $i += 1
            $newFName = "$(get-Date $_.LastWriteTime -Format 'yyyyMMdd_hhmms')_$i$($_.Extension)"
        Copy-item $_.FullName "$destFld$newFld\$newFName"   # Copy file to new location with new filename.
        If (test-path "$destFld$newFld\$newFName") { remove-item $_.FullName -WhatIf} # Test if file was copied successfully. If so delete source.
    • #80410

      Davide Nota

      Many Thanks for your help Rick

      i added the $year variable to get the $year folder
      is working but if i re run the script is creating duplicates of existing file

      i am trying to edit in a way that if the destination file is present and have the same hash do nothing and go to next foreach
      otherwise continue to copy and nerame with _count if neded
      or if not present just copy

      sounds hard to understand i try with an example of how i think the code should be i haven't tested it yet

      Dir\File001.jpg——-zzz—-2009\2009_05_17\20090517_184024.jpg—–zzz——(first time script run copy file)
      Dir\dir\File002.jpg—xxx—-2009\2009_05_17\20090517_184024_1.jpg—xxx——(same name but diff hash add _count)
      dir\dir\file003.jpg—zzz——————————————–zzz——(skip as same hash file found)
      Dir\File002.jpg——-yyy—-2012\2012_05_11\20120511_132254.jpg—–yyy——(no same name found so copy)

      if (test-path "$destFld\$year\$newFld\$newFName") ¦
       Compare-object -ReferenceObject ($_ ¦ get-filehash))-DifferenceObject ($destFld\$year\$newFld\$newFName ¦ get-filehash))
      # if hash is the same do nothing and restart with next file
      # Sets the new file name
      $newFName = "$(get-Date $_.LastWriteTime -Format 'yyyyMMdd_hhmms')$($_.Extension)"
      #increments the file name if already exists.
      $i = 0
      While (test-path "$destFld\$year\$newFld\$newFName") {
      $i += 1
      $newFName = "$(get-Date $_.LastWriteTime -Format 'yyyyMMdd_hhmms')_$i$($_.Extension)"}
      # Copy file to new location with new filename
      Copy-item $_.FullName "$destFld\$year\$newFld\$newFName"
      # Test if file was copied successfully. If so delete source.
      If (test-path "$destFld\$year\$newFld\$newFName") { remove-item $_.FullName -WhatIf} 

You must be logged in to reply to this topic.