Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 批处理文件:列表目录&;单个变量的文件名,并显示为选择菜单_Windows_Shell_Variables_Batch File_Cmd - Fatal编程技术网

Windows 批处理文件:列表目录&;单个变量的文件名,并显示为选择菜单

Windows 批处理文件:列表目录&;单个变量的文件名,并显示为选择菜单,windows,shell,variables,batch-file,cmd,Windows,Shell,Variables,Batch File,Cmd,我在许多不同的windows机器上使用RDP,有时必须将RDP转换成一台,然后再从一台转换到另一台 我想知道是否有可能创建一个批处理文件,该文件可以读取设置路径中所有目录的名称,然后将它们显示为菜单中的编号变量。 输入所选内容后,它将对所选目录中的所有.rdp文件执行相同的操作 下面是一个我如何为每个文件手动硬编码的示例…但是我需要一些能够适应将新rdp文件放到目录中的东西,而不是每次在批处理文件中手动添加它,因为站点/PC的数量和名称可以定期更改 :site ECHO Location Lis

我在许多不同的windows机器上使用RDP,有时必须将RDP转换成一台,然后再从一台转换到另一台

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

下面是一个我如何为每个文件手动硬编码的示例…但是我需要一些能够适应将新rdp文件放到目录中的东西,而不是每次在批处理文件中手动添加它,因为站点/PC的数量和名称可以定期更改

: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
我发现了几个与此类似的问题(如and),但它们似乎都只是显示一个列表,而不是将它们放入类似菜单的选项中,而且我仍然不完全理解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,然后batch将每个子目录名称存储到一个编号的变量中,并将它们回显到屏幕上并提示选择

Location List

1 NSW
2 QLD

Enter Selection:_
Machine List for NSW

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

Enter Selection:_
如果用户输入1,那么它会将QLD子目录中的每个.RDP文件名存储到一个编号的变量中,并将它们回显到屏幕上并提示选择

Location List

1 NSW
2 QLD

Enter Selection:_
Machine List for NSW

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

Enter Selection:_
在用户此时进行选择后,我希望使用所选的.rdp文件和mstsc命令来启动到所选计算机的rdp会话,然后循环返回开始,以允许同时打开第二个连接

如果您能提供任何帮助,我将不胜感激。

这里有一种方法:

@echo off
setlocal enabledelayedexpansion

:Start
ECHO Location List
ECHO.
ECHO NSW
ECHO QLD
ECHO.
SET /p site=Enter Selection: 

for /f %%a in ('dir /b/s "c:\Temp\%site%\*.rdp"') do (
  set /a i+=1
  echo !i! - %%~nxa
  set mach[!i!]=%%~nxa
)
set /p m0=Enter Selection: 
echo mstsc !mach[%m0%]! /console
set /p sel=Would you like to launch another [y/n]? 
if /i "%sel%" EQU "y" Goto :start

另外,这是假设您的所有服务器都是2003。从2008年开始,我相信/console已经取代了/admin。如果是这样的话,根据您所连接的服务器的版本,很容易添加更多的逻辑

这里有一种方法:

@echo off
setlocal enabledelayedexpansion

:Start
ECHO Location List
ECHO.
ECHO NSW
ECHO QLD
ECHO.
SET /p site=Enter Selection: 

for /f %%a in ('dir /b/s "c:\Temp\%site%\*.rdp"') do (
  set /a i+=1
  echo !i! - %%~nxa
  set mach[!i!]=%%~nxa
)
set /p m0=Enter Selection: 
echo mstsc !mach[%m0%]! /console
set /p sel=Would you like to launch another [y/n]? 
if /i "%sel%" EQU "y" Goto :start
@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

另外,这是假设您的所有服务器都是2003。从2008年开始,我相信/console已经取代了/admin。如果是这样的话,根据您所连接的服务器的版本,很容易添加更多的逻辑

@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\uu
开头的所有变量。对
s\uu
没有什么特别的意义-这正是我选择的。如果存在
s_…
变量,则
set s_
的输出形式为
s_whatever=something
。如果不存在,则
2>nul
会抑制错误消息,但需要用插入符号(^)对>进行转义,以告知
cmd
重定向是要执行的命令的一部分,而不是
for
命令的一部分。如果
s_whatever=something
,则/f的
将使用=作为分隔符解析该行,从而将
s_whatever
分配给指定的元变量
%%i

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

整个文件名被分配给
%%a
,因为
delims=”“
即没有分隔符
S\uuu
用作通用变量,并在
%%a
中分配文件名的驱动器和路径部分。然后删除
s\uuu
的最后一个字符(它将是a\),并且/f%%b
将结果字符串解释为一个文件名。然后设置变量
s#site
s_@site_machine
(设置为Y,但可以设置为任何值)

注意
的用法!s:~0,-1
指定将运行时值的字符0..last-1作为
s
-的值!指定
SETLOCAL ENABLEDELAYEDEXPANSION
处于活动状态时的运行时值

主例程的其余部分只需使用各种参数调用两次
SHOWMENU
,并将
s
中返回的值分配给相应的变量

SHOWMENU
将项目数(
s_items
)设置为比可用项目数多1,清除屏幕并从第一个子例程参数(
%1
)显示菜单标题-但引号被抑制(
%1
)-这允许参数包含空格

下面的
FOR/F
标记了
s#
(站点名称)或
s@
(站点+机器名称)的
SET
列表。使用分隔符u和=以及#或@意味着对于像
s_35;NSW=Y
这样的行,将
NSW
分配给
%i
,而像
s_@NSW\Server01=Y
这样的行将
NSW
分配给
%i
Server01
分配给
%j

选择适当的零件并将其传递给SHOWLINE例程

s
然后用于用户输入。强制清除意味着如果用户只按ENTER键,它将保持未设置状态,否则它将保留其原始值

我已经任意分配了一个
Q
输入来退出,如果没有用户输入,那么也会退出。否则,如果设置了变量
s_choicemade
,则将
s_
设置为该值,并从子例程返回到达
EOF
。如果做出无效选择,则不会设置
s_invalidchoice
,因此将重新显示菜单

SHOWLINE
过程将
s_
设置为空格lineNumber.space,然后显示参数(
%1
),前面是最后4个字符