1

我已经搜索并搜索以找到解决(感觉如何)一个独特问题的方法。这里的许多答案都非常有帮助,并且让我走了很长一段路,但最后一点让我很难过。

  • 我的批处理文件需要在具有变量名的文件夹中打开可执行文件
  • 此文件夹可能位于两个目录之一中
  • 这是我最初拥有的并且有效

    @ECHO OFF
    SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
    
    SET DIR1="%USERPROFILE%\AppData\Local\Application Workspace\Profiles"
    SET DIR2=C:\Application\SRW\Profiles
    
    IF NOT EXIST %DIR1% (
       GOTO PROFILE_2
     ) ELSE (
       GOTO PROFILE_1
     )
    
    :PROFILE_1
    for /f "delims=" %%A in ('dir %DIR1% /ad /b') do (
         set foldername=%%~nxA
         )
    SET DIR1=%DIR1:"=%
    SET DIR=%DIR1%\%foldername%\app.exe
    GOTO START_APP
    
    :PROFILE_2
    for /f "delims=" %%A in ('dir %DIR2% /ad /b') do (
         set foldername=%%~nxA
         )
    SET DIR=%DIR2%\%foldername%\app.exe
    GOTO START_APP
    
    :START_APP
    START "" /b "%DIR%"
    
    :EOF
    ENDLOCAL
    EXIT
    

然后,当我发现某些用户可能在变量配置文件文件夹中有多个配置文件并且他们需要能够选择哪个配置文件用于该给定任务时,我被抛出了一个曲线球。现在我有一个变量配置文件文件夹和该文件夹中的一个或多个变量配置文件。

我找到了列出文件夹名称并将它们显示在命令窗口中以供选择的代码。

@echo off
cls
setlocal EnableDelayedExpansion

set /a count=0

for /d %%d in (*) do (
    set /a count+=1
    @echo !count!. %%d 
)
setlocal DisableDelayedExpansion

set /P selection="select folder number:"

我还发现这个例程允许用户从列表中选择一个文件,然后它应该将该文件名转换为一个变量。

批处理脚本编程——如何允许用户从文件夹中的文件列表中按编号选择文件?

不幸的是,我无法让链接中的示例按原样工作,而且我不知道如何使其与文件夹名称一起工作,因为文件夹名称示例和文件名示例很接近但不够接近,我无法理解该怎么做. 即使它以某种方式确实可以工作,那么我怎样才能在上面发布的原始代码中进行这样的例程工作呢?

另外,如果只有一个文件夹,我真的不希望用户被迫选择文件夹。如果仅存在一个文件夹,则应自动将其放入文件夹名称变量中,并且根本不会向用户显示任何内容。

我正在尝试做的事情甚至可能吗?

非常感谢任何帮助。

4

2 回答 2

3
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION 
::
:: Set count-of-targets and application name
::
SET /a targets=0
SET appname=app.exe
SET "dots=..."
::
:: clear all "$" variables
::
FOR /f "delims==" %%i IN ('set $ 2^>nul') DO SET "%%i="
::
:: look for app.exe in (1) userprofile... (2) \application\srw...
::
SET dir1="%USERPROFILE%\AppData\Local\Application Workspace\Profiles"
SET dir2="C:\Application\SRW\Profiles"
:: My testing - my directory names
SET dir1="c:\sourcedir"
SET dir2="C:\destdir\test dir"
FOR %%s IN (%dir1% %dir2%) DO (
 FOR /f "delims=" %%i IN ('dir /s /b "%%~s\%appname%"') DO ( CALL :process "%%~dpi"
 )
)
::
:: Now have TARGETS=#hits; $_n=full pathname; $n=directoryname
::
IF %targets%==1 SET mychoice=1&GOTO chosen
::
:: repeat a menu
::
:again
CLS
FOR /l %%i IN (1,1,%targets%) DO (
 IF %%i lss 10 (ECHO(%%i%dots%%dots:~0,1%!$%%i!) ELSE (ECHO(%%i%dots%!$%%i!)
)
SET mychoice=
SET /p mychoice="Please choose 1..%targets% : "
IF NOT DEFINED $_%mychoice% GOTO again
:chosen

CALL SET application="%%$_%mychoice%%%%appname%"

ECHO START "" /b %application%

GOTO :EOF
::
:: Parameter is quoted-full-pathname
::
:process
SET /a targets+=1
SET $_%targets%=%~1
SET $=%~1
FOR %%n IN ("%$:~0,-1%") DO SET $%targets%=%%~nxn
GOTO :eof

从你所说的,这应该有效。

第一步是设置。设置找到的目标数量和实际应用程序名称,并清除所有以“$”开头的变量名。

下一步是指定要使用的目录。我只是复制了你的,然后用适合我机器的设置覆盖了这些设置——当然,你需要删除那些覆盖的行。请注意,名称应设置为引号...

接下来,从应用程序的每个目录扫描。每次找到实例时,调用:process传递完整终止的路径名。

:process增加找到的目标的计数并将变量设置为$_n传递的完整路径名(取消引用)然后设置$为取消引用的完整路径名并使用语法技巧FOR找到应用程序的直接目录。%$:~0,-1%是完整路径名减去最后一个字符 -\所以结果看起来像一个文件名。然后将该“文件名”分配给$n

目录扫描完成后,%targets% 将包含目标数量。如果那是 1,那么我们就拥有了我们所需要的一切——我们只能选择目标编号 1,所以这是为我们选择的。

否则,清除屏幕并显示多行 - %targets% to be precise. The format isn...immediadirname`,如果目标数少于 10,则会添加一个额外的点,以便长列表可以很好地排列。然后询问行号。

在这一点上,唯一$_存在的变量是$_1..$_%targets%所以如果 $_%mychoice% 存在,它必须是一个有效的选择。如果没有定义,那么重复这个问题......

CALLing SET application="%%$_%mychoice%%%%appname%" 先解析命令,然后再解析。在第一次解析之后,该行变为 (if mychoice=3) SET application="%$_3%app.exe" so on the second occasion,application` 被正确设置为应用程序的完整名称 - 并被引用。

我的应用程序没有多大意义starting,因为它不存在,所以我只是echo编辑了它。


鉴于扩展要求:

您可能是从捷径开始的。假设您运行该快捷方式最小化并在SETLOCAL

SET "poweruser=%1"

添加,之后

IF %targets%==1 SET mychoice=1&GOTO chosen

线

IF NOT DEFINED poweruser START "%username% - poweruser" "%~dpnx0" poweruser&GOTO :EOF 

并改变

GOTO :EOF

就在标签:process之前

EXIT

因此,如果它不是在 poweruser 模式下运行(因此未定义)并且poweruser不是1 (我假设它不会为 0)那么该用户尚未在快捷方式中设置为 poweruser,但确实有多个目标,因此在超级用户模式下重新启动作业(即最大化。)%targets%

请注意,在 - 之后的字符串实际上并不重要,"~dpnx0"只要它是一个字符串即可。我刚刚使用poweruser它的作用是告诉批处理它正在正常窗口中运行,而不是最小化。

对于 powerusrs,如果您喜欢将快捷方式设置为normal windowmaximised并在命令行中在批处理名称之后放置一个参数,您可以这样做,这将稍微加快过程。让它不带参数并最小化将适合所有用户,因为如果找到超过 1 个目标,它将自动调整。

我试过这个。它对我有用。

于 2013-06-12T08:27:04.057 回答
1

我分两步回答了你的问题。在第一个中,我将您的原始代码翻译成更易读的代码。这里是:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION

SET "DIR1=%USERPROFILE%\AppData\Local\Application Workspace\Profiles"
SET DIR2=C:\Application\SRW\Profiles

IF NOT EXIST "%DIR1%" (
   for /f "delims=" %%A in ('dir %DIR2% /ad /b') do (
      SET DIR=%DIR2%\%%~nxA\app.exe
   )
) ELSE (
   for /f "delims=" %%A in ('dir %DIR1% /ad /b') do (
      SET DIR=%DIR1%\%%~nxA\app.exe
   )
)

START "" /b "%DIR%"
ENDLOCAL
EXIT

您应该首先检查以前的代码是否与您的原始代码相同。

在第二步中,我将配置文件选择添加到前面的代码中:

@ECHO OFF
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION

SET "DIR1=%USERPROFILE%\AppData\Local\Application Workspace\Profiles"
SET DIR2=C:\Application\SRW\Profiles

IF NOT EXIST "%DIR1%" (
   for /f "delims=" %%A in ('dir %DIR2% /ad /b') do (
      SET DIR=%DIR2%\%%~nxA\app.exe
   )
) ELSE (
   call :SelectProfile
)

START "" /b "%DIR%"
ENDLOCAL
EXIT


:SelectProfile

rem Get a list of folders in User Profile dir
set count=0
for /f "delims=" %%A in ('dir %DIR1% /ad /b') do (
   set /A count+=1
   SET DIR[!count!]=%DIR1%\%%~nxA
)

rem Initialize the selected profile
set select=1
if %count% equ 1 goto endSelection

rem Show the profiles menu
cls
echo Available profiles:
echo/
for /L %%i in (1,1,%count%) do echo   %%i- !DIR[%%i]!
echo/

rem Let's the user to select the profile
:select
set select=1
set /P "select=Enter number of desired profile [first one]: "
if not defined DIR[!select!] goto select

:endSelection
SET DIR=!DIR[%select%]!\app.exe
exit /B

请注意,如果用户在答案中输入空格,则先前的代码将失败。如果需要,可以修复此细节。

于 2013-06-12T12:40:36.050 回答