【问题标题】:Batch - Search for part/exact name and copy line from text file into batch as var批处理 - 搜索部分/确切名称并将文本文件中的行复制到批处理中作为 var
【发布时间】:2015-04-12 09:56:37
【问题描述】:

以下信息包含在一个文本文件中,格式如下。

/var/www/xxx/html/videos/video_folder_1
/var/www/xxx/html/videos/video_folder_2
/var/www/xxx/html/videos/video_folder_3
/var/www/xxx/html/videos/video_folder_4
/var/www/xxx/html/videos/video_folder_5
/var/www/xxx/html/videos/video_folder_6
/var/www/xxx/html/videos/video_folder_7

我在已经定义的批处理文件中还有一个名为%file_name% 的变量。

所以可以说是%file_name% = V001-video_folder_6.mp4

如您所见,还有更多额外信息,V001-.mp4

我想使用 var %file_name% 来搜索文本文件并返回整行。在这种情况下,它将返回/var/www/xxx/html/videos/video_folder_6,然后将此信息放入一个新的变量中,比如%folder_path%

我想我会使用findstr,但是我一直在玩,并没有得到最好的结果。

【问题讨论】:

    标签: batch-file automation


    【解决方案1】:

    使用findstr 的方法的问题在于它们很慢,因为它们每次都需要执行findstr.exe(大约30KB 的文件)。一个更简单/更快的解决方案是在array 的帮助下仅使用内部批处理命令。如果要处理的名称数量很大,可能会标记两种方法之间的时间差异。

    @echo off
    setlocal EnableDelayedExpansion
    
    rem Load the lines from text file into an array with the last part as index:
    for /F "delims=" %%a in (test.txt) do (
       set "line=%%a"
       for %%b in (!line:/^= !) do set "lastPart=%%b"
       set "folder[!lastPart!]=%%a"
    )
    
    set "file_name=V001-video_folder_6.mp4"
    
    rem Get the folder from file_name:
    for /F "tokens=2 delims=-." %%a in ("%file_name%") do set "folder_path=!folder[%%a]!"
    
    echo Folder path is: %folder_path%
    

    【讨论】:

    • 每次是什么意思? findstr 在包含文件夹路径的文本文件上只执行一次。这就是我使用 Sysinternals 的 Process Monitor 在执行我在此处发布的批处理代码时看到的。
    • @Mofi:发布示例中的%file_name% 代表一个文件。如果实际问题中必须处理多个文件,则必须对每个文件执行一次findstr.exe 命令。 “如果要处理的文件数量很大,则可能会标记两种方法之间的时间差异”。例如,对于两三百个文件,findstr 方法可能需要几分钟,但不使用任何外部 .exe 命令的方法只需要一小部分时间。当然,只处理几个文件的时间并不重要(但这点仍然成立)。
    • 但是这种方法有几个问题。首先,正如目前所写的那样,它不适用于V001-VIDEOS for school (Miss Patrick).mp4,因为在这种情况下环境变量是folder[Patrick)]。任何其他名称中带有空格的文件/文件夹名称也会导致批处理代码无效,当然可以修复。其次,默认情况下,为环境变量保留的内存非常小。因此,如果文本文件包含很多路径,即有几个 MB,则此方法将很快出现内存问题。
    • @Mofi:嗯,自 Windows XP 发布以来,为环境变量保留的内存并不是“相当小”。如this MS page 中所述,最大环境大小为 64 MB(请查看“设置环境变量”下方的注释)。只有 1 MB 的空间足以容纳 26,843,546 条路径,类似于 OP 发布的路径,因此您所说的所谓的“内存问题”将出现在 1,717,986,944 条路径之后。我认为这根本不是“非常快”......
    • 天哪! 10 多年来,我一直认为 65,536 KB 意味着 65536 字节(64 KB),因为在德语中,逗号是十进制分隔符,点是千位分隔符,我无法想象缓冲区真的是 64 MB。但是我可以通过一个简单的测试看到,注释和您是对的,总环境变量内存为 64 MB。 Aacini,非常非常感谢。
    【解决方案2】:

    让我们假设发布的行在当前工作目录中的文件Test.txt 中。

    @echo off
    set "file_name=V001-video_folder_6.mp4"
    for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
    for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
        set "folder_path=%%P"
        goto NextCommand
    )
    :NextCommand
    echo Full folder path is: %folder_path%
    

    打开命令提示符窗口,输入命令for /?,按RETURNENTER 键并阅读输出帮助以了解这个小代码。

    FOR 循环内的命令goto 导致在找到包含感兴趣文件夹路径的第一个行之后立即退出findstr.exe 的循环处理输出。

    如果在文本文件中找不到搜索的文件夹,可能会更好:

    @echo off
    set "file_name=V01-VIDEOS for school (Miss Patrick).mp4"
    for /F "tokens=2 delims=-." %%A in ("%file_name%") do set "folder=%%A"
    for /F "delims=" %%P in ('%SystemRoot%\System32\findstr.exe "/C:%folder%" Test.txt') do (
        set "folder_path=%%P"
        goto FoundFolder
    )
    echo "%folder%" not found in file Test.txt.
    pause
    goto :EOF
    :FoundFolder
    echo Full folder path is: "%folder_path%"
    pause
    

    【讨论】:

    • 这是一个很好的例子。我正在尝试。
    • 您无需在第一次查找后终止它,因为根据 OP,每个文件中只会找到一个实例。除此之外,您的代码与我的代码几乎相同,但有一些不必要的改动。
    • 这很好,但是有一些东西可以作为容错的手段。目前名称为set file_name="V001-VIDEOS_sub.mp4" 只是作为一种测试手段。如果文件名是V000000000000001-VIDEOS_sub.mp4" 它可以工作。如果它是V034234201-VIDEOS_sub.mp4qwewqeq" It works which means the -` 和. 是非常重要的,没有那么它就不起作用。这是完美的。但是这不起作用V001-VIDEOS sub.mp4。有空间。有没有办法通过空格来管理这个。
    • 几乎相同的批处理代码(是的,Monacraft 和我有相同的想法,Monacraft 只是比我快一点)也适用于文件夹名称中的空格。 Arthor,用你在批处理文件和Test.txt 中发布的文件夹名称试试,你会看到你得到了正确的输出。
    • @Arthor,括号对我上面发布的批处理代码也没有问题。再试一次。注意:在您使用%folder_path% 的任何字符串中,您必须将完整的字符串用双引号引起来,否则空格或括号会成为问题。但是贴出的代码本身在文件夹名称中的空格和括号没有问题。
    【解决方案3】:

    这应该可行:

    ::file_name=V001-video_folder_6.mp4
    ::file containing folder paths is called paths.txt
    
    for /f "tokens=2 delims=-." %%a in ("%file_name%") do set FN=%%a
    for /f %%a in ('findstr /E /L "%FN%" "paths.txt"') do set folder_path=%%a
    echo %folder_path%
    

    你想要的实际上是两行。

    【讨论】:

    • 这是一个很好的例子。我正在尝试。
    • 这很好,但是有一些东西可以作为容错的手段。目前设置名称为 file_name="V001-VIDEOS_sub.mp4" 只是作为一种测试手段。如果文件名是 V000000000000001-VIDEOS_sub.mp4" 它工作。如果它是 V034234201-VIDEOS_sub.mp4qwewqeq" 它工作这意味着 -` 和 .非常重要,没有它就行不通。这是完美的。但是,这不起作用 V001-VIDEOS sub.mp4。有空间。有没有办法通过拥有空间来解决这个问题。我对你的代码也有同样的效果。
    • @Arthor,在 /f 之后插入第二个 FOR 循环 "delims=",正如我从代码开始所做的那样,Monacraft 的批处理代码也适用于文件夹名称中有空格。
    • 你是绝对正确的。请查看上面对 Monoacraft 的评论。谢谢
    猜你喜欢
    • 2014-01-28
    • 1970-01-01
    • 2010-11-29
    • 2019-04-20
    • 2018-01-19
    • 1970-01-01
    • 2016-09-04
    • 2022-11-28
    • 1970-01-01
    相关资源
    最近更新 更多