0

I need to call a program with a list of file names, but I need to find and extract the first file on the list taken as sorted order and pass the rest to the program.

Specifically, I want to pass a list of files selected with the QTTabbar application launcher and execute exiftool so that the first file on the list is used for the "-TagsFromFile" option, and then process all of the rest of the files so that they get the "-AllDates" option applied. So my first attempt was:

exiftool -TagsFromFile %1 -AllDates %*

This would put the first file on the list, but since exiftool would be setting it to the same value as it already has, that would be acceptable.

However, I discovered that QTTabbar did not pass the arguments to the batch file in the lexigraphically sorted order by name as I was expecting. So I figured I needed to sort the list.

I found the way to sort the arguments in How to sort the arguments dropped to a batch file? but in that solution there is a loop and a program is invoked once for each argument, rather than building a new argument list.

for /f "delims=" %%a in ('cmd /c ^"for %%i in ^(%*^) do @echo %%~i^"^|sort') do (
    echo use "%%a"
)

Instead of "echo use "%%a", I need to build a new argument list that I can pass to exiftool. Ideally I could build a list and then replace the original argument list with the new one, like the "set" command in Bash. Failing that, I could build a new list and use that, but I don't know how to build a list and I don't know how to reference the first element if I had one.

How do I do this?

EDIT: The files are selected in the File Explorer GUI. The order they are presented to the batch file is determined by Windows. Here is the output of "echo %*" from the batch file:

"C:\Users\user1\Desktop\setAB.test\00000920.jpg" "C:\Users\user1\Desktop\setAB.test\00000913.jpg" "C:\Users\user1\Desktop\setAB.test\00000914.jpg" "C:\Users\user1\Desktop\setAB.test\00000915.jpg" "C:\Users\user1\Desktop\setAB.test\00000916.jpg" "C:\Users\user1\Desktop\setAB.test\00000917.jpg" "C:\Users\user1\Desktop\setAB.test\00000918.jpg" "C:\Users\user1\Desktop\setAB.test\00000919.jpg"

As you can see, the last file appears first. I don't know why. Sometimes they are in reverse order.

So, the batch file gets invoked as:

ex.bat "C:\Users\user1\Desktop\setAB.test\00000920.jpg" "C:\Users\user1\Desktop\setAB.test\00000913.jpg" "C:\Users\user1\Desktop\setAB.test\00000914.jpg" "C:\Users\user1\Desktop\setAB.test\00000915.jpg" "C:\Users\user1\Desktop\setAB.test\00000916.jpg" "C:\Users\user1\Desktop\setAB.test\00000917.jpg" "C:\Users\user1\Desktop\setAB.test\00000918.jpg" "C:\Users\user1\Desktop\setAB.test\00000919.jpg"

And I want exiftool to run as:

exiftool -TagsFromFile "C:\Users\user1\Desktop\setAB.test\00000913.jpg" -AllDates "C:\Users\user1\Desktop\setAB.test\00000913.jpg" "C:\Users\user1\Desktop\setAB.test\00000914.jpg" "C:\Users\user1\Desktop\setAB.test\00000915.jpg" "C:\Users\user1\Desktop\setAB.test\00000916.jpg" "C:\Users\user1\Desktop\setAB.test\00000917.jpg" "C:\Users\user1\Desktop\setAB.test\00000918.jpg" "C:\Users\user1\Desktop\setAB.test\00000919.jpg" "C:\Users\user1\Desktop\setAB.test\00000920.jpg"
  • 1
    Open a Command Prompt window, type `shift /?` and press the `[ENTER]` key, to read about a command which may be useful to you. It would also assist us greatly, if you were to provide us with some example input, explain exactly how that input is being passed to the script, and show us exactly the exiftool command complete with those inputs in the required order etc. – Compo Apr 12 '21 at 13:09
  • The shift doesn't help since the original order isn't correct. For an example: ex.bat f4 f3 f8 f7 f6 f1 f2 f5 Inside the ex.bat file I need to call exiftool like this: exiftool -TagsFromFile f1 -AllDates f2 f3 f4 f5 f6 f7 f8 Optionally f1 could also appear on the second set so it might be f1 f2 f3 f4 f5 f6 f7 f8. – Brian Utterback Apr 12 '21 at 13:47
  • Could you please post a real world example of what is being passed into the batch file. Your pseudo example is flawed because F10 will sort after F1 and before F2 with the SORT command. – Squashman Apr 12 '21 at 14:21
  • You were asked to show us exactly how you are passing the input to the batch file. If you're typing it in at the command line, as shown in your example, then type it in in the correct order. If that argument list is being supplied from another command or program, then please show us the command which produces it. Now your comment above, unlike that in your previous comment, is supplying all of those aguments as doublequoted, please be specific, it really does matter, when it comes to getting a robust solution. – Compo Apr 12 '21 at 14:33
  • So based on the arguments that are supplied to the batch what should the `EXIFTOOL` command look like? Again use the real world example you supplied and [edit] your question. Could you please take some time to read [ask] a good question as well. – Squashman Apr 12 '21 at 14:54

2 Answers2

2

So your code was really close. All you needed to add were a few basic concepts to get the first argument into a variable which can be done by checking if a variable is defined or not. Then use the SET command to rebuild all the arguments back into another variable. This requires delayed expansion as described in this question.

@ECHO OFF
setlocal enabledelayedexpansion
set "first="
set "all="
for /f "delims=" %%a in ('cmd /c ^"for %%i in ^(%*^) do @echo %%~i^"^|sort') do (
    if not defined first set "first=%%~a"
    set "all=!all!"%%~a" "
)
exiftool -TagsFromFile "%first%" -AllDates %all%
endlocal
Squashman
  • 13,649
  • 5
  • 27
  • 36
  • @BrianUtterback I am sure it would be helpful for everyone if you read, [What should I do when someone answers my question?](https://stackoverflow.com/help/someone-answers) Then go back to all of your questions and take the appropriate action. – Squashman Apr 12 '21 at 17:15
1

Very similar to the method already provided by Squashman, but suitable for filepaths containing ! characters.

@For %%G In (First Rest) Do @Set "%%G="
@For /F "Delims=" %%H In (
    '"(For %%G In (%*) Do @Echo "%%~G") | %SystemRoot%\System32\sort.exe"'
) Do @If Not Defined First (Set "First=%%H") Else (SetLocal EnabledelayedExpansion
    For /F "Delims=" %%I In ("!Rest!%%H") Do @EndLocal & Set "Rest=%%I")
exiftool.exe -TagsFromFile %First% -AllDates %Rest%
Compo
  • 36,585
  • 5
  • 27
  • 39