如何正确地嵌套两个`forfiles`循环(以便内部体扩展两个迭代级别的变量)? [英] How to nest two `forfiles` loops properly (so that the inner body expands variables of both iteration levels)?

查看:223
本文介绍了如何正确地嵌套两个`forfiles`循环(以便内部体扩展两个迭代级别的变量)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试嵌套两个 forfiles 循环,以便内部循环的命令从两个都接收到 @ 变量外循环和内循环迭代。对于后者,需要为外部循环转义 @ 变量替换,以便内部 forfiles 命令接收变量

I am trying to nest two forfiles loops so that the command of the inner loop receives @ variables from both the outer and the inner loop iteration. For the latter the @ variable replacement needs to be escaped for the outer loop so that the inner forfiles command receives the variable name.

我有一个代码片段,枚举给定的目录( C:\root ),如果迭代的项目是自己的目录,则列出所有包含的文本文件( *。txt )。

但是,它不起作用如预期的那样:我试图逃避 @file \ 的扩展,但它扩展到外部循环:

I have got a code snippet that enumerates a given directory (C:\root), and if the iterated item is a directory on its own, all the contained text files (*.txt) are listed.
However, it does not work as expected: I tried to escape the expansion of @file with \, but it expands to the value of the outer loop:

2> nul forfiles /P "C:\root" /M "*" /C "cmd /C if @isdir==TRUE forfiles /P @path /M *.txt /C \"cmd /C echo @relpath -- \@file\""

除了 \ @ file ,还 ^ @ file ^^ @ file ^ ^^ @ file 0x40file 0x40 是十六进制字符代码的 @ )扩展为外部 forfile 变量的值。

\\\ @文件 ^^^^ @ file 展开为外部值,使用 \ ^ 分别。

即使 @ ^ file @ ^^文件(请参阅此帖)不起作用(后者扩展到 @file 字面上)。

Besides \@file, also ^@file, ^^@file, ^^^@file, 0x40file (0x40 being the hexadecimal character code representation of @) expand to the value of the outer forfiles variable.
\\@file and ^^^^@file expand to the outer value too, with \ and ^ preceeded, respectively.
Even @^file, @^^file (see this post) does not work (the latter expands to @file literally).

所以:有没有办法逃避更换 @ 变量(如 @file ,...)从外部 forfile forfiles iteration接收文字变量名称并将其扩展为其值?

So: is there a way to escape the replacement of @ variables (like @file,...) from the outer forfiles loop so that the inner forfiles iteration receives the literal variable name and expands it to its value?

我在Windows 7上工作64位。

I am working on Windows 7 64-bit.

注意

2 - ; nul 重定向应避免大量错误消息 ERROR:未找到类型为* .txt的文件。当当前处理目录中没有文件匹配给定面具( *。txt )。

Note:
The 2> nul redirection should avoid numerous error messages ERROR: Files of type "*.txt" not found. when no file in the currently processed directory matches the given mask (*.txt).

推荐答案

使用格式 0xHH forfiles 的十六进制字符代码替换功能,可以自行嵌套。在这种情况下,使用 00x7840 ,因此第一个(外部) forfile 循环替换 0x78 部分由 x 导致 0x40 ,这又由第二个(内部) forfile 循环替换为 @

The trick is to use the hexadecimal character code replacement feature of forfiles in the format 0xHH, which can be nested on its own. In this context, 00x7840 is used, hence the first (outer) forfiles loop replaces the 0x78 portion by x, resulting in 0x40, which is in turn resolved by the second (inner) forfiles loop by replacing it with @.

一个简单的 0x40 不 c $ c $ for C $ c>替换第一遍中的十六进制代码而然后它处理第二遍的 @ 变量,因此 0x40file 将被替换先通过 @file ,然后再通过外部 forfiles 循环扩展为当前迭代的项。

A simple 0x40 does not work as forfiles replaces hexadecimal codes in a first pass and then it handles the @ variables in a second pass, so 0x40file will be replaced by @file first and then expanded to the currently iterated item by the outer forfiles loop both.

以下命令行遍历给定的根目录,并显示每个直接子目录的相对路径(由外部 forfiles loop)和其中发现的所有文本文件(由$ forfiles 循环迭代):

The following command line walks through a given root directory and displays the relative path of each immediate sub-directory (iterated by the outer forfiles loop) and all text files found therein (iterated by the inner forfiles loop):

2> nul forfiles /P "C:\root" /M "*" /C "cmd /C if @isdir==TRUE forfiles /P @path /M *.txt /C 0x22cmd /C echo @relpath -- 00x7840file0x22"

输出可能看起来像(相对子目录路径剩下,文本文件正确):

The output might look like (relative sub-directory paths left, text files right):


.\data_dir -- "text_msg.txt"

.\logs_dir -- "log_book.txt"
.\logs_dir -- "log_file.txt"







代码说明


  • 如上所述, 00x7840file 部分将外部<$ c $部分隐藏 @file 变量名称c> forfiles 命令,并将其替换转移到内部 forfiles 命令;

  • 以避免任何麻烦引用 cmd / C ,在 / C 外部 forfiles 的切换可以通过说明它们的十六进制代码来避免 0x22 ;

    forfiles 支持转义引号,如 \ ,但是 cmd / C 不关心 \ ,因此它会检测到; 0x22 cmd 没有特殊的含义,所以它是安全的)

  • 如果语句检查外部 forfile 循环枚举的项目是否是一个目录,如果不是,则跳过内部 forfiles loop;

  • 如果枚举的子目录不包含与给定模式匹配的任何项目, forfiles 返回错误消息,如错误:找不到类型* .txt的文件。 at STDERR;为了避免这样的消息,重定向 2> nul 已被应用;

  • as described above, the 00x7840file portion hides the @file variable name from the outer forfiles command and transfers its replacement to the inner forfiles command;
  • to avoid any trouble with quotes " and cmd /C, quotes within the string after the /C switch of the outer forfiles are avoided by stating their hexadecimal code 0x22;
    (forfiles supports escaping quotes like \", however cmd /C does not care about the \ and so it detects the "; 0x22 has no special meaning to cmd and so it is safe)
  • the if statement checks whether the item enumerated by the outer forfiles loop is a directory and, if not, skips the inner forfiles loop;
  • in case the enumerated sub-directory does not contain any items that match the given pattern, forfiles returns an error message like ERROR: Files of type "*.txt" not found. at STDERR; to avoid such messages, redirection 2> nul has been applied;

步骤一步一步的更换:

Step-by-Step Replacement:

这是上面的命令行,但删除重定向,仅用于演示:

Here is the above command line again but with the redirection removed, just for demonstration:

forfiles /P "C:\root" /M "*" /C "cmd /C if @isdir==TRUE forfiles /P @path /M *.txt /C 0x22cmd /C echo @relpath -- 00x7840file0x22"

现在我们将提取嵌套命令行将要一个接一个执行。

We will now extract the nested command lines which are going to be executed one after another.

取上述示例输出第一行的项目( .\data_dir - text_msg.txt),外部 forfile 命令执行的命令行是:

Taking the items of the first line of the above sample output (.\data_dir -- "text_msg.txt"), the command line executed by the outer forfiles command is:

cmd /C if TRUE==TRUE forfiles /P "C:\root" /M *.txt /C "cmd /C echo ".\data_dir" -- 0x40file"

所以内部 forfiles 命令行看起来像( cmd / C 被删除,而如果条件满足):

So the inner forfiles command line looks like (cmd /C removed, and the if condition is fulfilled):

forfiles /P "C:\root" /M *.txt /C "cmd /C echo ".\data_dir" -- 0x40file"

现在执行的命令行内部 forfiles 命令是(注意在 .\data_dir 之间删除的文字引用,并立即更换 0x40file 通过变量值 @file ):

Now the command line executed by the inner forfiles command is (notice the removed literal quotes around .\data_dir and the instant replacement of 0x40file by the value of variable @file):

cmd /C echo .\data_dir -- "text_msg.txt"

通过这些步骤,从最内层到最外层的命令行,您可以嵌套两个以上的 forfile 循环。

Walking though these steps from the innermost to the outermost command line like that, you could nest even more than two forfiles loops.

注意:

所有路径或文件名相关的 @ - 变量被每个引用的字符串替换;然而,上面显示的示例输出不包含目录路径的任何周围的引号;这是因为 forfile > / C 切换;在这里输出它们,将 @relpath 在命令行中替换为 00x7822 @ relpath00x7822 ; \\\@ relpath\\\\也可以(但不建议不要混淆 cmd )。

All path- or file-name-related @-variables are replaced by quoted strings each; however, the above shown sample output does not contain any surrounding quotes for the directory paths; this is because forfiles removes any literal (non-escaped) quotes " from the string after the /C switch; to get them back in the output here, replace @relpath in the command line by 00x7822@relpath00x7822; \\\"@relpath\\\" works too (but is not recommended though to not confuse cmd).

由于 forfiles 不是一个内部命令,所以应该可以嵌套它,而没有 cmd / C 前缀,例如 forfiles / Cforfiles / M *,例如(除非使用任何额外的内部或外部命令,命令级联,重定向或管道,其中 cmd / C 是强制性的)。

但是,由于在 / C之后错误地处理命令行参数, code>切换 forfiles ,您实际上需要将其说明为 forfiles / Cforfiles f orfiles / M *,所以内部 forfiles 命令翻倍。否则会抛出一条错误消息( ERROR:无效的参数/选项)。

这篇文章中已经找到了最好的解决方法:无cmd / c的forfile文件(滚动到底部)。

Since forfiles is not an internal command, it should be possible to nest it without the cmd /C prefix, like forfiles /C "forfiles /M *", for instance (unless any additional internal or external command, command concatenation, redirection or piping is used, where cmd /C is mandatory).
However, due to erroneous handling of command line arguments after the /C switch of forfiles, you actually need to state it like forfiles /C "forfiles forfiles /M *", so the inner forfiles command doubled. Otherwise an error message (ERROR: Invalid argument/option) is thrown.
This best work-around has been found at this post: forfiles without cmd /c (scroll to the bottom).

这篇关于如何正确地嵌套两个`forfiles`循环(以便内部体扩展两个迭代级别的变量)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆