Reputation: 61
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"
Upvotes: 0
Views: 244
Reputation: 38623
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%
Upvotes: 1
Reputation: 14290
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
Upvotes: 3