1

I'm writing a rough .cmd batch to do an operation with a few files (4 or 5) in Windows. I want to mark the desired files in Explorer's checkboxes, and drag-and-drop them to the batch file, that will perform the operation (actually I'll put a shortcut in SendTo folder).

I need to control the order of the parameters (checked files), i.e., which checked file will be %1, which will be %2, and so on. It would be perfect if the order of parameters was the same order in which each file was checked; at least, if the files were in alphabetical order, I could, first of all, rename the files adding a number to them; the batch will send the filenames to an intermediary file, which will be sorted to another file, and the sorted file (in the desired order, achieved by numbering) will be used as source for the last operation.

But I wonder if could it exist anoter option that wouldn't need this intermediary file.

I made a few tests and I found no predictable order, neither alphabetical, nor related to the order in which the the boxes were checked. I suspect that the sequence of the command line parameters sent to the batch is the same order of their directory entries - but since Win10's CMD.COM doesn't execute "dir /ou", I wasn't able to verify this.

enter image description here

** TL;DR: I'm using Windows Explorer to select files that will be passed as parameters to a batch file, and I want to define, or at least preview, which of them will be %1, which will be %2, and so on. **

5
  • It's cmd.exe not cmd.com. Also, this site is for help to fix a problem with your code, whereas you require assistance with the internal workings of the OS, or one or more of its built-in applications. It is therefore better suited to another platform.
    – Compo
    Commented May 27 at 22:27
  • Not sure, but when you select files, they are "in that order", when you drag it, if you "grab" file grip2.tif, windows(should) pass grip2(as first), grip4(as second), grip.tif(as third). It will not remember what you picked first or last. Window action is hard-coded and it's "flow" can be tracked, not sure if you can "bypass" it in anyway to suit interaction to your needs between Window and CMD. Maybe create a txt file per folder to "fix" desired order of files selection? You might be better of in powershell, tell it what file to pick and dictate your own "order" there, get more freedom.
    – Danijel
    Commented May 28 at 5:07
  • @Compo The mistaken mention of CMD.COM only reveals that I come from an ancient past, but does not hinder the understanding of the issue in any way. Congratulations for your attention and thank you for moving the question forward, in fact it should have been posted on SuperUser from the beginning.
    – mguima
    Commented May 28 at 21:01
  • @Danijel The "batch" file is to be used to merge a few JPG or PDF files that will be rotated, converted to 2 sheets per page, and merged again. These operations are complex to just be done selecting the files and merging them in a PDF utility. Yes, I could use Powershell, but CMD.EXE is enough. I'm terrible with Powershell, I'm a native speaker of COMMAND.COM / 4DOS dialect, hence my familiarity with CMD.EXE. Later I learned to do everything I needed in bash. But in this case I'm in Windows and I wanted do just drag the files.
    – mguima
    Commented May 28 at 21:19
  • @mguima, on the contrary, legacy users, myself included, should have remembered that to be named COMMAND.COM, and no reason therefore for me not to mention it in a comment regarding Windows 10. You are welcome that I helped migrate your question to the appropriate platform.
    – Compo
    Commented May 29 at 17:56

2 Answers 2

2

When you drag files from/in File Explorer, it starts from the file you click/drag from, and then goes through them in the current sort order.

When the file list is ordered by file name or file size, that is the order it will be passed on. When you drag from the first file, the list will be passed fully in order. If you drag from the middle file, it will be the second half before the first half of the list.


I just verified this behavior in Windows 11 File Explorer and a batch file. When sorted by file name, it is in that order. When sorted by file size, it is in that order.

@for %%x in (%*) do @echo %%x
pause

files, ordered by size (for non-alphabetic order)

3.txt
1.txt
2.txt
4.txt
5.txt
7.txt

dragged from file 5:

[…]\5.txt
[…]\7.txt
[…]\3.txt
[…]\1.txt
[…]\2.txt
[…]\4.txt
0

This does not need "check-boxes to be active, i think it works with them just as fine, it wont/shouldn't care.

  • Deselecting is not handled
  • It's set to 4 files/folders/whatevertheris to select
  • It will offer you to pick one of your opened File Explorers, assuming you know in what order you opened them, this number needs to be entered(if more then one explorer is opened)
  • It will go wild so you can play with it, each time you pick next file, you can start switching from batting ^^ to scripting (add "[console]::beep(2204,160);[console]::beep(2222,150)" if you want it to play to you)

You probably want to place your batch where SelectionList.txt is made, in code ;) you can mix them both and call it from PS. Save this anywhere(i guess) as "AnyName.ps1", right click and "Run with PowerShell..."

# Get the script directory
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path

# Change some UI properties
$MyUI = (Get-Host).UI.RawUI
$MyUI.ForegroundColor = "cyan"
$MyUI.BackgroundColor = "black"
$MyUI.windowtitle = "Selections counting."

# Function to get all open File Explorer windows
function Get-OpenFileExplorerWindows {
    $shellApp = New-Object -ComObject Shell.Application
    $shellWindows = $shellApp.Windows()
    $explorerWindows = @()
    foreach ($window in $shellWindows) {
        if ($window.Name -eq "File Explorer") {
            $explorerWindows += $window
        }
    }
    return $explorerWindows
}

# Function to get the selected files from a specific File Explorer window
function Get-SelectedFilesFromWindow {
    param (
        $window,
        [ref] $selectedFilesLog
    )    
    $selectedItems = $window.Document.SelectedItems()
    $selectedFiles = @()    
    foreach ($item in $selectedItems) {
        if ($item.Path -notin $selectedFilesLog.Value) {
            $selectedFilesLog.Value += $item.Path
            $selectedFiles += $item.Path
        }
    }    
    return $selectedFiles
}

# Prompt the user to select a File Explorer window to track
function SelectFileExplorerWindow {
    $explorerWindows = Get-OpenFileExplorerWindows
    if ($explorerWindows.Count -eq 0) {
        $MyUI.ForegroundColor = "red"
        $MyUI.BackgroundColor = "darkred"
        Write-Output "No File Explorer windows are currently open."
        pause
        exit
    }
    
    Write-Output "Select a File Explorer window to track:"
    for ($i = 0; $i -lt $explorerWindows.Count; $i++) {
        $window = $explorerWindows[$i]
        Write-Output "$($i + 1): $($window.LocationName) - $($window.LocationURL)"
    }
    
    $selection = Read-Host "Enter the number of the File Explorer window to track"
    $selectedIndex = [int]$selection - 1
    if ($selectedIndex -lt 0 -or $selectedIndex -ge $explorerWindows.Count) {
        $MyUI.ForegroundColor = "red"
        $MyUI.BackgroundColor = "darkred"
        Write-Host "$selection is Invalid selection. Script will now Exit."
        pause
        exit
    }
    return $explorerWindows[$selectedIndex]
}

# Select a File Explorer window to track
$selectedWindow = SelectFileExplorerWindow
Write-Output "Tracking File Explorer window: $($selectedWindow.LocationName)"

# Monitor for changes
$selectedFilesLog = @()

while ($true) {
    $newSelections = Get-SelectedFilesFromWindow -window $selectedWindow -selectedFilesLog ([ref]$selectedFilesLog)
    if ($selectedFilesLog.Count -ge 4) {
        if ($newSelections.Count -gt 0) {
            # Log the selected files to SelectionList.txt
            $logFilePath = Join-Path -Path $scriptDir -ChildPath "SelectionList.txt"
            $selectedFilesLog | Out-File -FilePath $logFilePath
            $MyUI.ForegroundColor = "green"
            $MyUI.BackgroundColor = "black"
            Write-Output "Newly selected files:"
            $selectedFilesLog | ForEach-Object { Write-Output $_ }

            $MyUI.windowtitle = "We got them all $($selectedFilesLog.Count)!"
            Write-Output "Four files selected. Exiting script."
            Pause #or Start-Sleep -Seconds 1
            exit
        }
    } else {
        if($selectedFilesLog.Count -eq "1" -OR $selectedFilesLog.Count -eq "3") {
            $MyUI.ForegroundColor = "blue"
            $MyUI.BackgroundColor = "darkblue"
        } else {
            $MyUI.ForegroundColor = "cyan"
            $MyUI.BackgroundColor = "black"
        }
        cls #or Clear-Host
        Write-Output "Less than four files selected. Total selected: $($selectedFilesLog.Count)"
        $MyUI.windowtitle = "Selected $($selectedFilesLog.Count)"
    }
    $MyUI.ForegroundColor = "cyan"
    $MyUI.BackgroundColor = "black"
    Start-Sleep -Milliseconds 250 #If mouse gets wrong sorting, reduce this to speed up capture
}

You must log in to answer this question.

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