【问题标题】:For Command help - nested command对于命令帮助 - 嵌套命令
【发布时间】:2013-12-26 22:00:59
【问题描述】:

我创建了以下简单的批处理文件....我在这里尝试完成的是使用远程命令(RCMD 实用程序)连接到(clusters.txt)中定义的服务器列表并删除列表视频文件在(assets.txt)中定义......我想删除每台服务器上的这些资产。这个批处理文件可以工作,但是它必须连接和断开连接才能删除每一个资产,而这正是我想要避免的。我希望能够连接到 1 台服务器并使用 scp del cmd 删除我的资产列表 %%B,然后断开与该服务器的连接并转到列表 %%A 上的下一个服务器,并从那里删除所有资产连接,而不必连接和断开 200 次。

@echo off

FOR /F "tokens=*" %%A IN (clusters.txt) DO FOR /F "tokens=*" %%B in (assets.txt) DO rcmd \\%%A \vstrmkit\scp del %%B

这是文件列表的样子:

11E8A51A*
11E8A51D*
11E8A614*
11E88E4E*
11E88E4C*

服务器列表只是带有字母和数字的计算机主机名:

SEA88630-N0

任何帮助将不胜感激。

【问题讨论】:

  • “您的文件列表”文件和“服务器名称”文件中是否只有一行?还是一个值=一行?
  • Sachadee,我每个服务器和每个文件都有一行,所以我有大约 30 个服务器(每行 1 个)和 120 个文件(120 行,每个文件 1 个)。
  • 客户端和服务器的操作系统是什么?
  • @MC ND 这是Windows server 2003

标签: batch-file for-loop command-prompt


【解决方案1】:

在不知道操作系统的服务器和客户端版本的情况下,可能会有某种命令行限制。但是,让我们试试

@echo off

    rem prepare environment
    setlocal enableextensions enabledelayedexpansion

    rem Define the command that will be executed for each element
    set "command=echo \vstrmkit\scp del"

    rem Prepare the command for the list of files into a environment variable
    set "command=set c=%command% "
    for /f "tokens=*" %%f in (assets.txt) do set "command=!command!/@c@%%~f"

    rem Adjust the command variable to generate a valid concatenation of commands
    set "command=%command:/=&%"

    rem Connect to each of the servers sending the generated command
    rem In the last step, change the @ with ! to generate on remote, when
    rem delayed expansion is applied, the correct final command to execute
    setlocal disabledelayedexpansion    
    for /f "tokens=*" %%a in (clusters.txt) do rcmd \\%%a cmd.exe /v:on /c "%command:@=!%"

请注意,在定义主命令的那一行,插入了一个echo 用于测试。如果一切正常,请删除 echo 以使其正常工作。

已编辑 - 选项编号 2

引号似乎有问题。前面的代码在我的系统中有效,但在 OP 中无效。让我们试试另一个。它也适用于我的系统。

@echo off

    rem prepare environment
    setlocal enableextensions disabledelayedexpansion

    rem Define the command that will be executed for each element
    set "command=echo \vstrmkit\scp del"

    rem Define a temporary file to contain commands to process
    set "tempFile=%temp%\%~nx0.tmp"

    rem Generate the content of the temp file with the list of commands
    rem to execute for each server
    (
        for /f "tokens=*" %%f in (assets.txt) do echo %command% %%f
        echo exit 
    ) > "%tempFile%"

    rem Connect to each of the servers sending the generated command list
    for /f "tokens=*" %%a in (clusters.txt) do (
        rcmd \\%%a < "%tempFile%"
    )

    del /f /q "%tempFile%" > nul 2>nul

    endlocal

【讨论】:

  • 你好 MC ND,服务器是 Windows server 2003。谢谢你帮我把这个放在一起,我现在就去试试。我会尽快通知你结果。
  • C:\Temp\Deletes&gt;test.bat Executing on \\sea80003-n0: cmd.exe /v:on /c set c=echo \vstrmkit\scp dir &amp;!c!11E8A51A*&amp;!c!11E8A51D*&amp;!c!11E8A614* '!c!11E8A51A*' is not recognized as an internal or external command,
  • 这就是我得到的:C:\Temp\Deletes&gt;test.bat Executing on \\sea80003-n0: cmd.exe /v:on /c set c=echo \vstrmkit\scp dir &amp;!c!11E8A51A*&amp;!c!11E8A51D*&amp;!c!11E8A614* '!c!11E8A51A*' is not recognized as an internal or external command, 为了安全起见,我将命令更改为scp dir。我希望以下命令与每个文件一起循环,所以如果我有一个包含 20 个文件的列表,那么我需要scp del file1* scp del file2* scp del file3* 我需要文件末尾的星号因为每个文件都有3个附加扩展名,所以它看起来像这样 file1 file1.vvx file1.fr file1.ff
  • @pbesk18:rcmd 处理某些引号的方式存在问题。我已经改变了一行,现在看起来set "command=set c=%command% "(更新了答案)。我已经通过 XP(我手头唯一的东西)安装了 rcmd(来自 Windows 2000 Resource Kit)并尝试了。现在它似乎可以正常工作,但它不是同一个环境。立即尝试。
  • 感谢您的快速回复@MC ND:我现在正在尝试!这就是我得到的:C:\Temp\Deletes&gt;test2.bat Executing on \\sea80106-n0: cmd.exe /v:on /c set c=echo \vstrmkit\scp dir &amp;!c!11e8A8B6* '!c!11e8A8B6*' is not recognized as an internal or external command, operable program or batch file. Remote server \\sea80106-n0 disconnected
【解决方案2】:
@ECHO OFF
SETLOCAL

SET "filelist="
FOR /f "delims=" %%A IN (assets.txt) DO CALL SET filelist=%%filelist%% %%A
FOR /F "tokens=*" %%A IN (clusters.txt) DO echo rcmd \\%%A \vstrmkit\scp del %filelist%
GOTO :EOF

所需的命令只是ECHOed 用于测试目的。确认命令正确后,将ECHO rcmd改为rcmd执行删除


如果命令不能接受多个参数的可能解决方案:

创建一个名为delasset.bat 的批处理文件并将其复制到每台目标机器上的\vstrmkit 或每台机器的path 上的某个其他目录中(例如c:\windowsc:\windows\system32

delasset.bat 应该包含

@ECHO OFF
ECHO DEL %*

(同样,我只是 ECHOed DEL - 您需要在验证激活后删除 echo

然后将...rcmd \\%%A \vstrmkit\scp del %filelist%改为...rcmd \\%%A \vstrmkit\scp DELASSET %filelist%

(不区分大小写;我已将其大写以强调)


另一种可能的方式:

@ECHO OFF
SETLOCAL

SET "filelist="
FOR /f "delims=" %%A IN (assets.txt) DO CALL SET filelist=%%filelist%%:%%A
SET filelist=%filelist:~1%
FOR /F "tokens=*" %%A IN (clusters.txt) DO echo rcmd \\%%A \vstrmkit\scp del %filelist::=^&\vstrmkit\scp del %
GOTO :EOF

应该生成(例如)

rcmd \\SEA88630-N0 \vstrmkit\scp del 11E8A51A*&\vstrmkit\scp del 11E8A51D*&\vstrmkit\scp del 11E8A614*&\vstrmkit\scp del 11E88E4E*&\vstrmkit\scp del 11E88E4C*

请注意,filelist 现在使用冒号分隔项目。冒号不能是文件名的一部分。第一个字符(这将是一个冒号,因为filelist 附加了:filenamefromfile)然后被剥离(请参阅子字符串文档提示中的set/?

%filelist::=^&amp;\vstrmkit\scp del % 中的象形文字意思是'带有文件列表,用字符串&amp;\vstrmkit\scp del 替换(第一个:)[第一个:= 之间的字符-恰好是一个冒号] (即= 和结束% 之间的所有字符 - 附加修改是因为&amp; 是cmd 的特殊字符(这意味着'在&amp; 之前做事,然后在之后做事' ) &amp; 需要用插入符号 (^) “转义”,表示“这是我想用作普通字符的特殊字符”。

echo 牢牢固定在原位将使您能够准确地看到应该交付的内容。可悲的是,我不知道它是否正确......

【讨论】:

  • Magoo,谢谢你的帮助,明天我上班的时候我会测试这个,我会让你知道它是否有效,希望它会。再次感谢。我看到你只使用了一个变量,这是一个错误吗?
  • 一点也不。第一个for 循环将每一行从assets.txt 构建成filelist,用空格分隔。 call ..%%var%%... 语法访问 var 的 RUN-TIME 值,因此更改是累积性的。一旦 for 完成,任何对 %%A 的引用也完成了。发出的命令将是 rcmd...del 11E8A51A* 11E8A51D* ... - 这应该有效,因为 del arg1 arg2... 会根据每个 arg 交付的内容进行删除。不确定rcmd 对此有何感受 - 我自己从未使用过它,因此需要用户验证。
  • 感谢 Magoo 的澄清,很好的解释... 'scp del' cmd 必须在每个资产上运行,它不适用于多个文件,因此 'scp del' 11E8A51A*(与一开始它将删除 3 个具有相同名称但扩展名不同的附加文件)但是要删除两个具有不同名称的完全不同的文件我需要运行 scp del file#1 然后 scp del file#2 所以 scp del arg1 arg2 (如果arg1 arg2... 是列表中的下一个新文件,那么我认为它不会起作用,但我一定会尝试的。我需要命令 'scp del' 来循环文件列表中的每个文件。跨度>
  • 我测试过,是的,该命令不能接受多个参数。结果如下:Remote server \\sea80174-n0 disconnected Executing on \\sea80178-n0: \vstrmkit\scp dir 11E8A51A* 11E8A51D* 11E8A614* 11E88E4E* 11E88E4C* 11E88CE8* 11E88CDA* 11E88B67* 11E87027* 11E86FCF* 11E86F26* 11E86EDB* SCP-E-SYNTAX, file "11E86EDB*" not found, error ERROR_FILE_NOT_FOUND Free Space: 23,587,717,120 (22495 MB) ...我想避免将故障转移复制到 50 台服务器。所以第一个选项不起作用,我会试试这个rcmd \\SEA88630-N0 \vstrmkit\scp del 11E8A51A* 这可能会做到。谢谢!
  • 第二个选项不起作用,因为 scp 无法执行 C:\Temp\Deletes&gt;rcmd \\SEA80005-N0 \vstrmkit\scp dir 11E8A51A*&amp;\vstrmkit\scp dir 11E8A51D*&amp;\vstrmkit\scp dir 11E8A614*&amp;\vstrmkit\scp dir 11E88E4E*&amp;\vstrmkit\scp dir 11E88E4C*&amp;\vstrmkit\scp dir 11E88CE8*&amp;\vstrmkit\scp dir 11E88CDA*&amp;\vstrmkit\scp dir 11E88B67*&amp;\vstrmkit\scp dir 11E87027*&amp;\vstrmkit\scp dir 11E86FCF*&amp;\vstrmkit\scp dir 11E86F26*&amp;\vstrmkit\scp dir 11E86EDB* Executing on \\sea80005-n0: \vstrmkit\scp dir 11E8A51A*&amp;\vstrmkit\scp dir 11E8A51D*&amp;\vstrmkit\scp dir 我将命令更改为 scp dir 以获取目录列表。
【解决方案3】:

这样的事情应该会有所帮助。 我现在不知道你在文件名后面有一个*,但它必须被删除 剧本。或者那是.* ???

编辑:如果您有各种具有相同名称的文件和各种(“未知”)扩展名,那么您必须使用新的 FOR 循环测试扩展名:

@echo off
setlocal EnableDelayedExpansion

FOR /F "tokens=*" %%A IN ('type clusters.txt') DO (
            FOR /F "tokens=*" %%B in ('type assets.txt') DO (
                     set $asset=%%B
                     rcmd.exe \\%%A \vstrmkit\scp del !$asset:~0,-1!.*))

【讨论】:

  • 我在文件名后面有一个 * 因为文件名有 3 个附加文件,所以当我运行这个命令 [scp del 11E8A51A*] 它会删除所有文件 11E8A51A.ff 11E8A51A.fr 11E8A51A.vvx 11E8A51A .我明天上班时会试试这个......非常感谢你的帮助,如果它有效,我明天会告诉你。我需要星星在那里,这样我也可以删除所有这些文件。
  • 命令与文件一起循环,但是,rcmd 也在循环,我不需要它循环我也没有看到 !asset 被资产文件名替换。它连接然后运行scp del !asset 然后它断开连接并再次连接以通过列表中的下一个文件,因此它正在执行许多重新连接,一旦它连接我需要 `\vstrmkit\scp del !asset' 循环直到它删除列表中的所有资产,然后它将断开连接并转到下一个服务器。我需要每个文件的星号,1 个文件有 4 个不同的分机 (即:11e8432a 11e8432a.ff 11e8432a.fr 11e8432a.vvx)
  • 那么我的第一个解决方案应该可以工作。测试新的编辑
  • 这就是我得到的:Executing on \\sea80003-n0: \vstrmkit\scp dir $asset:0,-1.* SCP-E-SYNTAX, file "$asset:0,-1.*" not found, error VSTRM_INVALID_OBJECT_NAME Free Space: 2,333,834,477,568 (2225718 MB) Total Space: 10,975,219,548,160 (10466785 MB) 我确保这些视频文件在视频服务器上。 C:\vstrmkit&gt;scp dir 11e80fd0* \SeaFileDevices\ files 24-Apr-2012 04:41:07 PM 2,956,645,356 \SeaFileDevices\DVL\11E80FD0 24-Apr-2012 04:41:11 PM 394,207,424 \SeaFileDevices\DVL\11E80FD0.ff
  • 抱歉,我忘记了变量 !$asset:~0,-1!.* 中的“~”。已更正
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
  • 1970-01-01
  • 2021-12-20
  • 2011-08-15
相关资源
最近更新 更多