在bat

时间:2016-12-10 12:30:03

标签: windows batch-file cmd

好的,所以我一直在这里贴墙(嘿嘿)。 我正在寻找一个选项/代码,允许我从.bat脚本中搜索部分路径和/或文件名,我将导出到外部文件。

现在,“搜索”,“导出”和“外部文件”是我很好的选择。令我头疼的部分是“部分”。

详细说明。 我正在寻找一个名为DATA的文件夹和一个名为userinfo.txt的文件。 那些是不变的。所以我的路径是DATA \ userinfo.txt 我也99%肯定这个文件夹将在D:\中,但这不是现在关注的问题。我会在哪里找到它。 但我无法弄清楚如何为我的生活寻找一个部分路径\文件名。

我已经指定DATA \ userinfo.txt是常量的原因是由于其他文件夹能够被任意命名。因此,在我的下面示例中,01-12-2016不必根据该约定命名。对于美国来说,它最有可能被命名为12-01-2016。它有时也被命名为20161201或20160112,或者最重要的是具有字母前缀,例如d01-12-2016。在那个音符上DATA总是DATA,这就是为什么我说DATA在我的搜索中是不变的。另外一件事是祖父母文件夹。当我说“相同”时,我指的是两个应用程序之间的“共享”。这并不意味着它总是被命名为“程序”,如下例所示。

谷歌搜索并使用我所知道的东西让我无处可去。

原因我不能简单地使用

where /r d: userinfo.txt

是该特定命令将返回数百个结果,因为为程序运行的每个.single.day创建了userinfo.txt并单独存储。

另外 - 如果有方法可以梳理数百个结果并找到匹配的部分来解决我的问题。

然而这引起了另一个令人头疼的问题,因为通常有多个程序使用这个确切的文件。

所以在

的例子中
d:\users\path\program\storage\01-12-2016\userinfo.txt
d:\users\path\program\otherstorage\01-12-2016\userinfo.txt
d:\users\path\program\storage\02-12-2016\userinfo.txt
d:\users\path\program\otherstorage\02-12-2016\userinfo.txt
d:\users\path\program\storage\03-12-2016\userinfo.txt
d:\users\path\program\otherstorage\03-12-2016\userinfo.txt
d:\users\path\program\storage\04-12-2016\userinfo.txt
d:\users\path\program\otherstorage\04-12-2016\userinfo.txt
d:\users\path\program\storage\05-12-2016\userinfo.txt
d:\users\path\program\otherstorage\05-12-2016\userinfo.txt
d:\users\path\program\storage\06-12-2016\userinfo.txt
d:\users\path\program\otherstorage\06-12-2016\userinfo.txt
d:\users\path\program\storage\data\userinfo.txt
d:\users\path\program\otherstorage\data\userinfo.txt

注意:存储,otherstorage,storageother,storage2,storagegh都是任意名称,因为这些文件夹的命名符合最终用户的意愿。 我想为

导出两个单独的变量
d:\users\path\program\storage

d:\users\path\program\otherstorage

我还需要为\ data \ userinfo.txt

执行此操作

因此,如果搜索\ data \ userinfo.txt,它将返回

d:\users\path\program\storage\data\userinfo.txt
d:\users\path\program\otherstorage\data\userinfo.txt

我也想隔离两个

d:\users\path\program\storage

d:\users\path\program\otherstorage

并将其用作(单独的)局部变量。

我需要注意的是,安装/下载任何外部脚本工具/辅助工具都不适合我在很多计/或外部下载/安装的足够权限,因此任何未集成到球棒中并且需要单独导入的内容都是一个坏主意。

此外,我正在使用Windows XP SP3,但我需要这款游戏能够在XP SP2,XP SP3,Windows 7,Windows 10,Windows NT,Windows 2000上运行。

任何帮助都将不胜感激。

请注意

d:\users\path\program

也是一个可接受的变量。在这种情况下,我会手动修改路径的其余部分,或者依赖最终用户(我的同事)输入来正确完成路径。最后证明是愚蠢的差事。

到目前为止,我一直在处理的方法是查找我知道将在两个文件夹中的.exe。这是我编写的代码的一部分,以匹配当前示例。

@echo off
SETLOCAL
echo Program will now look for program.exe and programgh.exe. Please input, when asked, matching part of the path for these files.
echo Example:
echo d:\users\path\program\storage\bin\program.exe
echo d:\users\path\program\otherstorage\bin\programgh.exe
echo In above example matching part is d:\users\path\program so you would enter that when prompted
echo Please do not input the last pathing mark: \ (backslash)
echo -------------searching---------------
::I am exporting errors to nul as I don't want them to be spammed by errors and other data that they would think is their fault
where /r c: program*.exe 2>nul
where /r d: program*.exe 2>nul
where /r e: program*.exe 2>nul
where /r f: program*.exe 2>nul
set /p dualpath="Please enter matching paths for program folder: "

之后我将继续使用%dualpath%变量。

正如通常发生的那样(至少对我而言),大多数人只是复制示例路径而不看看程序吐出的内容,并且会混淆程序无法运行的原因。或者将所有内容复制到program.exe和programgh.exe - 包括otherstorage \ bin \,而不会注意到\ storage \和\ otherstorage \不匹配。

我认为这现在涵盖了所有评论或其他问题,并且更清楚地说明了我需要的内容。感谢大家的帮助,我希望这更容易理解。

3 个答案:

答案 0 :(得分:1)

如果Windows cmd命令允许(partially or fully qualified) path中的通配符,则必须仅在path leaf(即路径中的最后一个项目或容器)中使用通配符。但是,您可以应用findstr regex来缩小命令输出,例如如下:

where /r d:\ userinfo.txt | findstr /I "\\storage2*\\data\\userinfo.txt"

以上命令将输出缩小到路径结尾 \storage\data\userinfo.txt\storage2\data\userinfo.txt

另一个示例 - 使用\storageX\data\userinfo.txt将输出缩小到路径结尾,其中X无任何或任何十进制密码[0-9]

dir /B /S d:\userinfo.txt | findstr /I "\\storage[0-9]*\\data\\userinfo.txt"

将路径放入环境变量(使用_var前缀以便于下一次识别),例如_varstorage_varstorage2,...

@ECHO OFF
SETLOCAL EnableExtensions
for /F "delims=" %%F in ('
  dir /B /S "d:\userinfo.txt" ^| findstr /I "\\storage[0-9]*\\data\\userinfo.txt"') do (
    for /D %%D in ("%%~dpF..") do (
        set "_var%%~nxD=%%~fD"
        rem             %%~fD        path
        rem      %%~nxD              last item in above path
        rem  _var                    variable name prefix
    )
)
rem show result:
set _var

另请参阅下一个%%~nxD%%~D说明:Command Line arguments (Parameters): Parameter Extensions

答案 1 :(得分:0)

基于您的上述样本

@Echo off
Set Search=\\data\\userinfo.txt
pushd "D:\Users\path\program
For /f "Delims=" %%A in (
  'Dir /B/S/A-D userinfo.txt ^|findstr "%Search%$"'
) Do Call :Sub "%%~fA" "%%~dpA.."
Popd
Goto :Eof
:Sub FullName DrivePath
Echo Found  %~nx1
Echo in     %~dp1
Echo Granny %~nx2
Set "Granny=%~nx2"
Echo in     %~dp2
Echo -------

应该提供此输出(仅部分测试)

Found  userinfo.txt
in     D:\Users\path\program\storage\data\
Granny storage
in     D:\Users\path\program\
-------
Found  userinfo.txt
in     D:\Users\path\program\storage2\data\
Granny storage2
in     D:\Users\path\program\
-------

Search中的反斜杠必须加倍,因为它是findstr的转义字符

答案 2 :(得分:0)

如果我的意图正确,下面的脚本应该按照你想要的那样做:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_ROOT=D:\" & rem "D:\", "D:\users",..., or "D:\users\path\program"
set "_FILE=userinfo.txt"

rem // Initialise index:
set /A "INDEX=1"
rem // Search for the specified file in the given root directory:
for /F "delims=" %%F in ('dir /B /S "%_ROOT%\%_FILE%"') do (
    rem // Iterate once over the grandparent directory itself:
    for /D %%D in ("%%F\..\..") do (
        rem // Resolve the path of the grantparent directory;
        set "ITEM=%%~fD"
        rem // Initialise flag (non-empty means not yet stored):
        set "FLAG=#"
        rem // Toggle delayed expansion to avoid trouble with exclamation marks:
        setlocal EnableDelayedExpansion
        rem // Iterate over all currently stored grantparent paths:
        for /F "tokens=1,* delims==" %%V in ('2^> nul set $ARRAY[') do (
            rem // Clear flag in case current grandparent has already been stored:
            if /I "!%%V!"=="!ITEM!" set "FLAG="
        )
        rem // Check flag:
        if defined FLAG (
            rem // Flag is empty, so current grandparent needs to be stored:
            set "$ARRAY[!INDEX!]=!ITEM!"
            rem // Transfer stored grandparent over localisation barrier:
            for /F "delims=" %%E in ("$ARRAY[!INDEX!]=!ITEM!") do (
                endlocal
                set "%%E"
            )
            rem // Increment index
            set /A "INDEX+=1"
        ) else endlocal
    )
)
rem // Retrieving final count of grandparent directories:
set /A "INDEX-=1"

rem // Return stored grandparent paths:
set $ARRAY[

endlocal
exit /B

这会在您的情况下返回D:\users\path\programs\otherstorageD:\users\path\programs\storage,它们分别存储在变量$ARRAY[1]$ARRAY[2]中。由于数组样式变量,这种方法足够灵活,可以涵盖存在两个以上祖父目录的情况。