jjzjj

windows - 批处理文件: List Directory & File names to individual variables and display as selection menu

coder 2024-06-09 原文

我在许多不同的Windows机器上使用RDP,有时必须将RDP合并为一个,然后从那里rdp转移到另一个。

我想知道是否可以创建一个批处理文件,该文件可以读取设置路径中所有目录的名称,然后将它们显示为带编号的变量(如菜单)。
输入选择后,它将对所选目录中的所有.rdp文件执行相同的操作。

下面是一个示例,说明如何为每个文件手动进行硬编码...但是我需要一些可以适应于将新的rdp文件拖放到目录中的方法,而不必每次都在批处理文件中手动添加它,如数字网站/台数和名称可能会定期更改。

:site
ECHO Location List
ECHO.
ECHO 1 NSW
ECHO 2 QLD
ECHO.
SET /p site=Enter Selection: 
IF "%site%"=="1" GOTO NSW
IF "%site%"=="2" GOTO QLD    

:NSW
SET dirname=C:\Machine\NSW\
ECHO Machine List
ECHO.
ECHO 1 Client01.rdp
ECHO 2 Server01.rdp
ECHO 3 Server02.rdp
ECHO.
SET /p machine0=Enter Selection: 
IF "%machine0%"=="1" SET machine1=%dirname%Client01.rdp
IF "%machine0%"=="2" SET machine1=%dirname%Server01.rdp
IF "%machine0%"=="3" SET machine1=%dirname%Server02.rdp
GOTO connection

:connection
mstsc %machine1% /console

我发现了几个与此类似的问题(例如herehere),但它们似乎都只是在显示列表,而不是将它们带入菜单之类的选项,而且我仍然不完全了解FOR命令的工作原理。

目录结构示例。
C:\Batchfile.bat
C:\Machines\NSW\Client01.rdp
C:\Machines\NSW\Server01.rdp
C:\Machines\NSW\Server02.rdp
C:\Machines\QLD\Client01.rdp
C:\Machines\QLD\Client02.rdp
C:\Machines\QLD\Server01.rdp

基本目录将设置为C:\Machines,然后批处理会将每个子目录名称存储到一个编号变量中,并将它们回显到屏幕并提示选择。
Location List

1 NSW
2 QLD

Enter Selection:_

如果用户输入1,则它将把QLD子目录中的每个.RDP文件名存储到一个编号变量中,并将它们回显到屏幕并提示选择。
Machine List for NSW

1 Client01.rdp
2 Server01.rdp
3 Server02.rdp

Enter Selection:_

用户此时进行选择后,我想将所选的.rdp文件与mstsc命令一起使用,以启动与所选计算机的rdp session ,然后环回开始位置以允许同时打开第二个连接。

我会很感激您能提供的任何帮助。

最佳答案

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION 
FOR /f "delims==" %%i IN ('SET s_ 2^>nul') DO SET "%%i="
SET "sourcedir=c:\sourcedir"
FOR /f "delims=" %%a IN ('dir/s/b/a-d "%sourcedir%\*.rdp"') DO (
 SET s_=%%~dpa
 FOR /f %%b IN ("!s_:~0,-1!") DO SET s_#%%~nb=Y&SET s_@%%~nb_%%~na=Y
)
CALL :showmenu "Location List" #
IF /i "%s_%"=="q" GOTO :EOF
SET s_site=%s_%
CALL :showmenu "Machine List for %s_site%" @ %s_site%
IF /i "%s_%"=="q" GOTO :EOF
SET s_machine=%s_%
ECHO(==============
ECHO site=%s_site% machine=%s_machine%
GOTO :EOF

:showmenu
SET s_items=1
CLS
ECHO(%~1
ECHO(
FOR /f "tokens=2,3delims=_%2=" %%i IN ('set s_%2') DO (
 IF "%3"=="" (
  CALL :showline %%i
 ) ELSE (
  IF "%3"=="%%i" CALL :showline %%j
 )
)

ECHO(
SET "s_="
SET /p "s_=Enter Selection : "
IF NOT DEFINED s_ SET s_=Q
IF /i "%s_%"=="q" GOTO :EOF
IF DEFINED s_%s_% CALL SET s_=%%s_%s_%%%&GOTO :EOF 
GOTO showmenu

:showline
SET "s_= %s_items%. "
ECHO %s_:~-4%%1
SET s_%s_items%=%1
SET /a s_items+=1
SET "s_%s_items%="
GOTO :eof

这种方式是自我调整的。不幸的是,它也使用了一些象形文字。

第一步是确保从环境中删除所有名称以s_开头的变量。 s_没有特别的意义-这就是我选择的。如果存在set s_变量,则s_whatever=something的输出将采用s_...的形式。如果不存在,则2>nul会抑制该错误消息,但是>必须用脱字符号(^)进行转义,以告诉cmd重定向是要执行的命令的一部分,而不是for命令。如果是s_whatever=something,则for /f将使用=作为分隔符来解析该行,从而将s_whatever分配给指定的元变量%%i

下一步是查找从源目录开始的所有 .RDP 文件名。 dir /s/b/a-d产生完整文件名的裸线(无页眉或页脚),从而抑制任何碰巧与指定掩码匹配的目录名。

整个文件名都分配给了%%a,因为delims=""即没有定界符。 S_用作通用变量,并在%%a中分配了文件名的驱动器和路径部分。然后删除s_的最后一个字符(它将是\),并且for /f %%b会将结果字符串解释为文件名。然后将变量s_#sites_@site_machine设置为(Y,但是可以将其设置为任何值)

注意!s_:~0,-1!的使用,它指定采用s_的运行时值的字符0..last-1-!指定SETLOCAL ENABLEDELAYEDEXPANSION处于 Activity 状态时的运行时值。

主例程的其余部分简单地使用各种参数调用SHOWMENU两次,并将s_返回的值分配给适当的变量。
SHOWMENU将项目数(s_items)设置为比可用项目数多1,清除屏幕并显示第一个子例程参数(%1)的菜单标题-但取消引号(%~1)-允许该参数包含空格。

以下FOR/FSET列表标记为s_#(SITE名称)或s_@(SITE + MACHINE名称)。使用_和=以及#或@的定界符意味着对于像s_#NSW=Y这样的行将NSW分配给%%i,而像s_@NSW_Server01=Y这样的行将NSW分配给%%i,将Server01分配给%%j
选择适当的部分并将其传递给SHOWLINE例程。
s_然后用于用户输入。强制将其清除表示如果用户仅按ENTER键,则它将保持未设置状态;否则它将保留其原始值。

我已经任意分配了Q的输入以退出,如果没有用户输入,那也将退出。否则,如果设置了s_choicemade变量,则s_设置为该值,并且到达EOF从子例程返回。如果做出了无效的选择,则不会设置s_invalidchoice,因此将重新显示菜单。
SHOWLINE过程将s_设置为spacethelinenumber.space,然后在该字符串的后4个字符之前显示参数(%1)。这意味着,如果项目编号超过9,则前置空间将被截断,并且点将对齐。然后增加项目编号,以备下次选择。

关于windows - 批处理文件: List Directory & File names to individual variables and display as selection menu,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20048737/

有关windows - 批处理文件: List Directory & File names to individual variables and display as selection menu的更多相关文章

随机推荐