如何对 Windows 10 批处理文件中的参数列表进行排序
How to sort the argument list in a a Windows 10 batch file
我需要调用一个包含文件名列表的程序,但我需要找到并提取列表中的第一个文件并将其传递给程序。
具体来说,我想传递使用 QTTabbar 应用程序启动器选择的文件列表并执行 exiftool,以便列表中的第一个文件用于“-TagsFromFile”选项,然后处理所有其余文件文件,以便他们应用“-AllDates”选项。所以我的第一次尝试是:
exiftool -TagsFromFile %1 -AllDates %*
这会将第一个文件放在列表中,但由于 exiftool 会将其设置为与现有值相同的值,所以这是可以接受的。
但是,我发现 QTTabbar 没有像我期望的那样按名称的字典顺序将参数传递给批处理文件。所以我想我需要对列表进行排序。
我在 How to sort the arguments dropped to a batch file? 中找到了对参数进行排序的方法,但在该解决方案中有一个循环,并且为每个参数调用一次程序,而不是构建一个新的参数列表。
for /f "delims=" %%a in ('cmd /c ^"for %%i in ^(%*^) do @echo %%~i^"^|sort') do (
echo use "%%a"
)
我需要构建一个可以传递给 exiftool 的新参数列表,而不是“echo use”%%a”。理想情况下,我可以构建一个列表,然后用新的参数列表替换原始参数列表,比如Bash 中的“set”命令。否则,我可以构建一个新列表并使用它,但我不知道如何构建一个列表,也不知道如何引用第一个元素,如果我有一个。
我该怎么做?
编辑:
这些文件是在文件资源管理器 GUI 中选择的。它们呈现给批处理文件的顺序由 Windows 确定。这是批处理文件中“echo %*”的输出:
"C:\Users\user1\Desktop\setAB.test[=13=]000920.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000913.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000914.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000915.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000916.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000917.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000918.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000919.jpg"
如您所见,最后一个文件最先出现。我不知道为什么。有时它们的顺序是相反的。
因此,批处理文件被调用为:
ex.bat "C:\Users\user1\Desktop\setAB.test[=14=]000920.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000913.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000914.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000915.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000916.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000917.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000918.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000919.jpg"
我想要 exiftool 到 运行 作为:
exiftool -TagsFromFile "C:\Users\user1\Desktop\setAB.test[=15=]000913.jpg" -AllDates "C:\Users\user1\Desktop\setAB.test[=15=]000913.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000914.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000915.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000916.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000917.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000918.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000919.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000920.jpg"
所以您的代码非常接近。您需要添加的只是一些基本概念,以便将第一个参数放入变量中,这可以通过检查变量是否已定义来完成。然后使用 SET
命令将所有参数重建回另一个变量。这需要延迟扩展,如 .
中所述
@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 已经提供的方法非常相似,但适用于包含 !
个字符的文件路径。
@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%
我需要调用一个包含文件名列表的程序,但我需要找到并提取列表中的第一个文件并将其传递给程序。
具体来说,我想传递使用 QTTabbar 应用程序启动器选择的文件列表并执行 exiftool,以便列表中的第一个文件用于“-TagsFromFile”选项,然后处理所有其余文件文件,以便他们应用“-AllDates”选项。所以我的第一次尝试是:
exiftool -TagsFromFile %1 -AllDates %*
这会将第一个文件放在列表中,但由于 exiftool 会将其设置为与现有值相同的值,所以这是可以接受的。
但是,我发现 QTTabbar 没有像我期望的那样按名称的字典顺序将参数传递给批处理文件。所以我想我需要对列表进行排序。
我在 How to sort the arguments dropped to a batch file? 中找到了对参数进行排序的方法,但在该解决方案中有一个循环,并且为每个参数调用一次程序,而不是构建一个新的参数列表。
for /f "delims=" %%a in ('cmd /c ^"for %%i in ^(%*^) do @echo %%~i^"^|sort') do (
echo use "%%a"
)
我需要构建一个可以传递给 exiftool 的新参数列表,而不是“echo use”%%a”。理想情况下,我可以构建一个列表,然后用新的参数列表替换原始参数列表,比如Bash 中的“set”命令。否则,我可以构建一个新列表并使用它,但我不知道如何构建一个列表,也不知道如何引用第一个元素,如果我有一个。
我该怎么做?
编辑: 这些文件是在文件资源管理器 GUI 中选择的。它们呈现给批处理文件的顺序由 Windows 确定。这是批处理文件中“echo %*”的输出:
"C:\Users\user1\Desktop\setAB.test[=13=]000920.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000913.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000914.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000915.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000916.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000917.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000918.jpg" "C:\Users\user1\Desktop\setAB.test[=13=]000919.jpg"
如您所见,最后一个文件最先出现。我不知道为什么。有时它们的顺序是相反的。
因此,批处理文件被调用为:
ex.bat "C:\Users\user1\Desktop\setAB.test[=14=]000920.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000913.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000914.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000915.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000916.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000917.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000918.jpg" "C:\Users\user1\Desktop\setAB.test[=14=]000919.jpg"
我想要 exiftool 到 运行 作为:
exiftool -TagsFromFile "C:\Users\user1\Desktop\setAB.test[=15=]000913.jpg" -AllDates "C:\Users\user1\Desktop\setAB.test[=15=]000913.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000914.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000915.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000916.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000917.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000918.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000919.jpg" "C:\Users\user1\Desktop\setAB.test[=15=]000920.jpg"
所以您的代码非常接近。您需要添加的只是一些基本概念,以便将第一个参数放入变量中,这可以通过检查变量是否已定义来完成。然后使用 SET
命令将所有参数重建回另一个变量。这需要延迟扩展,如
@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 已经提供的方法非常相似,但适用于包含 !
个字符的文件路径。
@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%