Author Posts

September 22, 2017 at 11:08 am

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
Dir\Dir\file.*
Dir\Dir\file.*
Dir\file.*
file*

Desired Directory structure
Year\Year_MM_DD\YYYYMMDD_HHmmss.*
Year\Year_MM_DD\YYYYMMDD_HHmmss_1.*
Year\Year_MM_DD\YYYYMMDD_HHmmss_2.*
(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("System.windows.forms") |
     Out-Null     
#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
        }
        Else
        {
            Write-Error "Operation cancelled by user."
        }
    }

$folder = Select-FolderDialog
$folder
pause

#Desired Destination Directory Structure
$des_path = "$folder\$year\$new_folder_name"

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

#Command 
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)){
           $num+=1
       }
        else{break}
 }
    }
# If path does not exist rename file without a sequence number
$_.MoveTo($newpath)

else

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

September 22, 2017 at 3:28 pm

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.

}

September 23, 2017 at 8:03 pm

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

Example
Source—————-Hash—Destination—————————–Hash—–Comment
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
}
else
{
# 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} 
}