vitoco has asked for the wisdom of the Perl Monks concerning the following question:

Hi!

I want a running perl script to process every dropped file dragged from Explorer, but I don't know how drag&drop work in Windows.

I wrote this simple script as test.pl to get an idea of what is happening when it is running in its own window after a double click:

#!perl use strict; use warnings; while (<>) { print $_; }

The result is that if I drag one file to the Strawberry perl window, I can see the file's full path, but I have to press the Enter key with the focus in that window to make the script get the file, i.e. to print back the path. This means that only the file path name is sent to the script, without a newline.

What if I drag multiple files to the perl window? Only one filename is received, and no newline...

Is there a module or exteral tool that I could use in order to receive dropped files to the running window? Is adding the handler to the registry in order to run the script by dropping files to its icon the only way?

Thanks!!!

Edit: I first tried a oneliner in CMD with the same result.

perl -pe ""

Replies are listed 'Best First'.
Re: How to process dropped files
by Anonymous Monk on May 26, 2024 at 11:06 UTC
    What if I drag multiple files to the perl window? Only one filename is received

    What if you drop them onto just a cmd.exe (or PowerShell) window? The same happens, so it's not Perl limitation. Then either a proper GUI, or e.g. drop-target helper shortcut on Desktop which whole purpose would be to IPC received list to the main app, are required.

    I think quick/dirty/easy way could be to both receive either single dropped filename or a bunch/list from clipboard (i.e. user selects files, then just hits ctrl-C instead of dragging/missing/messing).

    Of course there are rough edges for you to solve. I have no idea if 50 ms timeout is good enough to prevent too many empty cycles, or why filenames being got from these 2 sources are encoded differently if not ASCII and/or quoted or not. But these "problems" should be trivial.

    use strict; use warnings; use feature 'say'; use Term::ReadKey; ReadMode 3; END { ReadMode 0 }; use Win32::Clipboard; Win32::Clipboard::Empty(); END { Win32::Clipboard::Empty() }; my @list; while ( 1 ) { if ( defined( my $char = ReadKey( .050 ))) { push @list, '' unless @list; $list[0] .= $char } elsif ( Win32::Clipboard::IsFiles() ) { push @list, Win32::Clipboard::GetFiles(); Win32::Clipboard::Empty() } elsif ( @list ) { say for @list; @list = () } }

      UPDATE!

      Instead of using the registry association of my script, I wrote a .BAT file that receives the dropped files in its icon and then it calls my perl script with all the received parameters (files):

      unifier.pl %*

      But I found something interesting: the working directory for the scripts was the source dir of the dragged files!!! I was expecting it to be the same dir where both the .bat and .pl files were located.

      I didn't hardcoded the paths in both script files. What I did was to create a shortcut to the .bat file. This allowed me to do two things: (1) Set the path of the working directory in its properties, and (2) change the icon to something that could be identified... I chose the pointing down arrow usually used for "download".

        good! i would test with filenames with spaces too

      I think quick/dirty/easy way could be to both receive either single dropped filename or a bunch/list from clipboard (i.e. user selects files, then just hits ctrl-C instead of dragging/missing/messing).

      That sounds interesting, but in this case the source is Irfanview's Thumbnail window, and it allows dragging selected images to other apps or to the Explorer, but it does not have the option to copy into the clipboard (it has its own copy menu).

      As my need is for a single time project, I think I'll take the drop into the script icon option. BTW, what I need is to visually select some images from hundreds of folders where the images are named by the same numbering sequence, and give a new name to the selected ones when copying them into the destination folder to avoid overwrites, like adding a prefix with the name of the folder from where it was taken.

      Thanks anyway!

Re: How to process dropped files
by bliako (Abbot) on May 26, 2024 at 12:34 UTC
    What if I drag multiple files to the perl window? Only one filename is + received, and no newline...

    I don't use windows, obviously, but wouldn't multiple fileNAMES be separated by newlines? And only the last would need pressing the enter key (or whatever the input line separator is)? So, I *guess*, in case of multiple filenames list pasted, you should get printed all the filenames except the last.

      I thought the same, but no, it only gives the name of one of them. I didn't check which of them (first selected, first in current sorting order, the last one...)

Re: How to process dropped files
by The_Dj (Scribe) on May 28, 2024 at 06:43 UTC
    You'll need to have a UI.
    I've done similar things using the Win32::GUI framework.

    If you aren't on windows, you get to use Tk, which is mostly equivalent but I can't help you with it.

      That could be a posibility, but I've never tried that framework. Then, it would take me more time to learn and program a UI than to process all the folders using the method I just described in my update.

      ... at the moment, I'm about to finish this year's folders. Almost three more years of folders are waiting!