end2endzone / ShellAnything

ShellAnything is a C++ open-source software which allow one to easily customize and add new options to *Windows Explorer* context menu. Define specific actions when a user right-click on a file or a directory.
MIT License
180 stars 27 forks source link

Repeating N times an <exec> element when N files are selected. #181

Open end2endzone opened 1 week ago

end2endzone commented 1 week ago

Is your feature request related to a problem? Please describe. When multiple files are selected, one can

  1. Feed all the selected files at once to a single <exec> element by setting selection.multi.separator property to " ". See selection.multi.separator section, example 1.
  2. Process each file individually by creating a multi-line batch file with the <file> element and then executing this batch file. See selection.multi.separator section, example 2.

In other words, ShellAnything allow processing a single <exec> element everytime. This is a limitation of the current implementation. It would be interesting to implement a mechanism that would process N times the <exec> element when having selected N files.

Describe the solution you'd like One way to implement this feature would be to define a new attribute to the <exec> element. I think changing the default behavior through an attribute would be the easiest way to understand how the selection needs to be processed. If the attribute is well named, it could also be intuitive. The attribute would define if the exec element needs to process all files at once or one by one.

For example, if one has selected the following picture files :

In the example above, assume one wants to to convert the images from CR2 format to JPG format. In such a scenario, it is more likely that a program is designed to convert a single image to another format. Image conversion programs are usually not designed to process multiple files all at once.

One could then define a special menu with an <exec> element to process each pictures individually such as :

<exec path="magick.exe" repeat="true" arguments="convert &quot;${selection.path}&quot; &quot;${selection.path}.jpg&quot;" />

When the repeat attribute is set to a value that evaluates to true, ShellAnything would then "expand" the <exec> element for each files allowing converting each file individually. This would result in something similar to the following:

<exec path="magick.exe" repeat="false" arguments="convert &quot;D:\Photos\New Year's Eve Party\DSCF7031.CR2&quot; &quot;D:\Photos\New Year's Eve Party\DSCF7031.CR2.jpg&quot;" />
<exec path="magick.exe" repeat="false" arguments="convert &quot;D:\Photos\New Year's Eve Party\DSCF7032.CR2&quot; &quot;D:\Photos\New Year's Eve Party\DSCF7032.CR2.jpg&quot;" />
<exec path="magick.exe" repeat="false" arguments="convert &quot;D:\Photos\New Year's Eve Party\DSCF7033.CR2&quot; &quot;D:\Photos\New Year's Eve Party\DSCF7033.CR2.jpg&quot;" />
<exec path="magick.exe" repeat="false" arguments="convert &quot;D:\Photos\New Year's Eve Party\DSCF7034.CR2&quot; &quot;D:\Photos\New Year's Eve Party\DSCF7034.CR2.jpg&quot;" />

By default, the attribute repeat would be set to false. This would be the default behavior since it is how previous versions are implemented.

Describe alternatives you've considered As stated previously and by other ShellAnything users, the current implementation is quite limited and a security concern when used to process multiple files.

Additional context N/A

end2endzone commented 1 week ago

More precision on how the "expansion" of the <exec> element could be implemented. If more than a single file is selected and the repeat attribute is set to a value that evaluates to true, ShellAnything would create process selected files one by one. When processing a single file, ShellAnything would update the selection-based properties.

For example, when processing file DSCF7033.CR2, the following properties would be set:

Property Updated values
selection.path D:\Photos\New Year's Eve Party\DSCF7032.CR2
selection.dir D:\Photos\New Year's Eve Party
selection.dir.count 35
selection.dir.empty false
selection.filename DSCF7032.CR2
selection.filename.noext DSCF7032
selection.parent.path D:\Photos\New Year's Eve Party
selection.parent.filename New Year's Eve Party
selection.filename.extension CR2
selection.drive.letter D
selection.drive.path D:\
selection.count 1
selection.files.count 1
selection.directories.count 0
selection.mimetype image/x-canon-cr2
selection.description Canon CR2 raw image data, version 2.0
selection.charset binary

For reference, a property which contains the index of the processed file could also be defined. For the example above, the property selection.index could be defined to 2. The property would be 1-based (the first value is 1, not 0).

mdnava commented 1 week ago

@end2endzone hi, me reporting here.

I'll copy/paste here what we discussed in https://github.com/end2endzone/ShellAnything/issues/108#issuecomment-2412942267

[== 3 ==]

I can select six (6) text files and code.exe will receive all of them in the same command, something like: code.exe "file1.txt" "file2.txt" "file3.txt" "file4.txt" "file5.txt" "file6.txt"

ShellAnything already supports this feature by default. See the Multi-selection-based properties section. This is the default behavior of selection.multi.separator property : it will add double quotes characters between arguments.

But I agree that this is not ideal and may be confusing a little.

Understood.. but I would think that usage of % ( and of %1 %2 %3 ...) is kinda universal. As for @ is just convenient to have a way to expand to a multiple command, instead of a single command.

Convenience is the key word. When you're writing long scripts and and long configuration files you just want a simple way to handle program parameters. I would say this is one of the reasons why batch files are still very much alive today, because of its simplicity to deal with params. It just works. I love how PowerShell allows for a plethora of new features and advanced parameters, but it can be somewhat overkill for simpler uses.

We are indeed in need of a better way to do this. I have created a new issue (#181) for brainstorming about this new feature. I would gladly appreciate any comment on the design of the new feature. I would also like that you add a comment so that I could give you the credit for the idea.

Understood, I'll comment and bookmark the issue.

Note that I do not really like the way @* seems to be handled in KuShellExt. In other words, I do not wish to have a special property that when used in the arguments attribute would trigger the <exec> element to process files one by one.

Well.. is just quick and convenient. However, every programmer can decide how to offer and handle features. Perhaps the exception would be when there are standards to follow. But even then sometimes following standards to the letter can be inconvenient. For example, PowerShell naming conventions recommend names that are very useful for a developer community, in the grand scheme of things, but at the same time recommended names can be too long and verbose for constant scripting and command line usage, so I tend to use shorter names.

In the end, I believe the truly important thing it would be, to have the feature available and easy to implement.

Other than that, I started looking at how I will design things to resolved this issue. Please be patient. Once I have a working candidate that solves this issue, I will release a new version of ShellAnything.

Understood!

——————————————————————————————

All that being said, I think the "repeat" attribute for this purpose would be a useful solution.

IMPORTANT: PROCESS LOCKING AND/OR CONCURRENCY ?

Locking the execution process is one thing to consider. Would the use of REPEAT lock the running process until it's finish to start the new iteration, or would iterations be executed concurrently (if it's even possible).

The way KuShellExt handles it is by locking the execution, so if I run ImageMagick to convert all PNG images on three folders to JPEG, it will run the first command, once the first folder is done, it will continue to the second, and then to the third folder. This makes sense and works, but can there be an option to execute concurrently ?

Best regards!