3

On windows, how can I set up a mechanism so that when I move a file into a directory where a file with the same name already exists, the new file is renamed randomly (or to <>.ext)?

Use case: I'm browsing cheezburger, drag and drop an image into a folder. Problem: all of them are named i.chzbgr.jpg => conflict. Windows offers to replace or not move, not even autorename ...

3
  • Yeah, windows does offer to keep both files. Not on an English Windows, but it says something like "Move, but keep both files", the new file will get the name "conflictingname(2)".
    – Martin
    May 27, 2013 at 21:46
  • @Martin: Not always. Copy a file to a dir. Try to copy/move the same file and Windows will ask to either: 1) Copy and Replace, 2) Don't copy, 3) Copy, but keep both files. However, now drag an image from within Firefox to a dir. Now drag it again to overwrite. You'll see options 1 and 2, but not 3. On IE it works somewhat, because when you drag/drop it copies from the Temporary Internet Files dir, so it's like just another normal copy operation. Of course, with IE seems one can't drag/drop hyperlinked images (I tried the gravatar above and it created an Internet Shortcut instead.)
    – Karan
    May 28, 2013 at 0:01
  • You're right, never realized that before, weird.
    – Martin
    May 28, 2013 at 0:32

3 Answers 3

1

Not a perfect solution, but I found and modified a script that monitors a folder for new files, when it detects a new file it automatically renames it with a random number. Copy paste the following and save it as a .ps1 file. Run it from powershell console or cmd. (make sure to enable running of ps scipts).

$folder = 'Q:\Test\# Downloads'  # <-- Change as desired
$filter = '*.*'
$fsw = New-Object IO.FileSystemWatcher $folder, $filter -Property @{
 IncludeSubdirectories = $false        
 NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
}
$onCreated = Register-ObjectEvent $fsw Created -SourceIdentifier FileCreated -Action {
 $path = $Event.SourceEventArgs.FullPath
 $name = $Event.SourceEventArgs.Name
 #$changeType = $Event.SourceEventArgs.ChangeType
 #$timeStamp = $Event.TimeGenerated
 if( $name -imatch "stop")
 {
    Unregister-Event -SourceIdentifier FileCreated;
    write-host "Monitoring stopped.";
    Exit(0);
 }
 else
 {
    $count=$(Get-Random -minimum 1 -maximum 999999);
    $p = Split-Path "$path" -Parent;
    $newName = "$p\$count-$name"
    while(test-path $newName)
    {
        $count=$(Get-Random -minimum 1 -maximum 999999);
        $newName = "$p\$count-$name";
    }
    Move-Item $path -Destination $newName -Force -Verbose
 }
}

Adding a file named "stop" to the folder stops the monitoring.

1
  • It's possible to use $folder = '.' to automatically listen in the folder where it is executed.
    – Qwerty
    Jun 21, 2021 at 17:37
1

I know it's a 3 year old thread, but maybe somebody (like me) will find this useful.

  1. Make a small folder such as "___Stage" somewhere simple, perhaps at the root of your photo or music storage.

  2. Open that folder in a separate small instance of [windows] explorer on the desktop somewhere. Make it just large enough in visual size to hold a single file in view -- I set about 2 inches square, and set the view mode to large icon to make it big enough to grab without being too accurate.

  3. Drag and drop your internet/firefox/chrome/etc. file to the view pane of that folder.

  4. Drag and drop AGAIN from this folder to your intended destination folder. This will be considered a directory to directory MOVE, which will unlock that magic option #3 "Move new file with (x) appended to rename and keep both files"

Viola.

I tried above just dragging to desktop, but this leaves the file still on the desktop unless you kill the "+" by holding the shift key (or shift mouse button if you have a multibutton mouse set up that way) For some reason win7 considers the desktop different than a directory.

I know this is cludgy, but you never have to take your hand off the mouse, or hunt down the naming conflict and rename it properly.

If you can't stand 01.jpg, 01(1).jpg, 01(2).jpg you'll have to rename them individually. I cannot fathom why win7 removed the #3 option functionality from the COPY option yet includes it in the MOVE option.

1
  • I tried it on Windows 10 and the only options I get now are 1) Replace the file in the destination, 2) Skip this file, 3) Compare info for both files. Compare allows picking both, but it takes exactly 4 clicks to achieve the desired result.
    – Qwerty
    Jun 21, 2021 at 17:25
0

Asyncrhonous watcher

  • Start with .\watch.ps1, stop with CtrlC
  • Listens in current folder
  • Listens on Created event. I also tried to add Renamed but it was failing for various reasons.
  • Appends -1 behind a file, x.jpgx-1.jpg
  • If such file exists, continues the line, x-1.jpgx-2.jpgx-3.jpg
watch.ps1
# Made by Qwerty https://superuser.com/questions/600550/autorename-files-with-identical-names-when-dropping-in-directory/1658155#1658155
# Inspired by https://powershell.one/tricks/filesystem/filesystemwatcher

# Run this script by '.\watch.ps1' to start watching current folder.
# Stop by pressing Ctrl+C

try {
  $watcher = New-Object IO.FileSystemWatcher -Property @{
    Path = '.'
    Filter = '*.*'
    IncludeSubdirectories = $true
    NotifyFilter = [IO.NotifyFilters]'FileName, LastWrite'
  }

  $action = {
    $details = $Event.SourceEventArgs
    $Path = $details.FullPath
    $Name = $details.Name
    $OldName = $details.OldName
    $filename = [io.path]::GetFileNameWithoutExtension($Name)
    $ext = [io.path]::GetExtension($Name)

    if ( $OldName -eq $null ) {
      $count = 0
      do {
        $count = $count + 1
        $newName = "$filename-$count$ext"
      } while ( test-path $newName )
      Move-Item $Path -Destination $newName -Force
      Write-Host ""
      Write-Host "$Name -> $newName" -ForegroundColor DarkYellow
    }
  }

  $handlers = . { # available event types: Created Deleted Changed Renamed
    Register-ObjectEvent -InputObject $watcher -EventName Created  -Action $action
  }

  # Monitoring starts now:
  $watcher.EnableRaisingEvents = $true
  Write-Host "Watching for changes. Press Ctrl+C to stop."

  # Use an endless loop to keep PowerShell busy.
  do {
    Wait-Event -Timeout 1
    Write-Host "." -NoNewline # write a dot to indicate we are still monitoring
  } while ($true)
} finally {
  # This gets executed when user presses CTRL+C:

  $watcher.EnableRaisingEvents = $false
  $handlers | ForEach-Object { Unregister-Event -SourceIdentifier $_.Name }
  $handlers | Remove-Job
  $watcher.Dispose()

  Write-Host ""
  Write-Host "Event Handler disabled, watching ends."
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .