使用批处理文件从TXT文件内的字符串设置变量

时间:2017-06-08 16:05:36

标签: string windows batch-file variables

我正在尝试为我公司的用户创建一个批处理文件,用于从旧的个人文件夹中迁移文件'网络共享到我们新的OneDrive实现。

问题是,我们的一些用户已将OneDrive的默认同步文件夹更改为他们想要的任何驱动器和路径,而不是保留默认值(* c:\ users \ username *)...例如,我用来测试我的BAT文件正在使用:

D:\ OneDrive - Business

然而,当它包含更多或更少的分隔符时仍然必须工作,例如 C:\ OneDrive C:\这就是我愚蠢存储的东西

此时,我已尝试使用REG QUERY从注册表中的UserFolder键输出到文本文件以获取路径,现在我尝试从文本文件中提取此路径有问题并将其设置为变量。创建的文本文件如下所示:

HKEY_CURRENT_USER\SOFTWARE\Microsoft\OneDrive\Accounts\Business1
    UserFolder    REG_SZ    D:\OneDrive - Business

我想要做的是设置" D:\ OneDrive - Business"到脚本化MOVE命令中使用的变量。

我的代码非常糟糕,除非有人认为有必要回答我的问题,否则我不会发布它。

我确信至少对你来说,这是孩子的游戏,所以我真的很感激为我提供的任何帮助!

谢谢!

4 个答案:

答案 0 :(得分:1)

以下是此任务的一个批处理解决方案:

@echo off
for /F "skip=1 tokens=1,2*" %%A in ('%SystemRoot%\System32\reg.exe QUERY HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Business1 /v UserFolder 2^>nul') do if /I "%%A" == "UserFolder" if not "%%C" == "" set "UserFolder=%%C" & goto UserFolderSet
echo No user folder for OneDrive found in Windows registry.
goto :EOF

:UserFolderSet
echo Found user folder: "%UserFolder%"

更好的可读性是这个版本完全相同:

@echo off
for /F "skip=1 tokens=1,2*" %%A in ('%SystemRoot%\System32\reg.exe QUERY HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Business1 /v UserFolder 2^>nul') do (
    if /I "%%A" == "UserFolder" (
        if not "%%C" == "" (
            set "UserFolder=%%C"
            goto UserFolderSet
        )
    )
)
echo No user folder for OneDrive found in Windows registry.
goto :EOF

:UserFolderSet
echo Found user folder: "%UserFolder%"

命令 FOR 在后台命令进程中执行命令 REG ,并捕获其输出,以处理 STDOUT

REG 输出错误消息以处理 STDERR 会因为2^>nul将其重定向到设备 NUL 而被抑制。重定向运算符>使用插入符^进行转义,这是解析 FOR 命令行时Windows命令解释器首先将>解释为文字字符所必需的。但稍后, FOR 2>nul执行带有> REG 命令行将被解释为重定向运算符。如果Windows注册表中根本不存在注册表值,则可能会出现错误消息。

FOR 通过使用空格和制表符作为分隔符(默认值)将行拆分为子字符串(标记)来处理 REG 命令的捕获输出的每个非空行。< / p>

选项skip=1指示 FOR 跳过第一行捕获的输出。

选项tokens=1,2*指示 FOR 第一个空格/制表符分隔符字符串,此处值名称UserFolder应分配给第一个循环变量A

第二个空格/制表符分隔的字符串在此类型REG_SZ应分配给循环变量B作为ASCII table中的下一个字符。现在应该清楚为什么循环变量区分大小写,而环境变量不区分大小写。这个循环变量在这里没有进一步处理,尽管在类型为REG_EXPAND_SZ而不是REG_SZ的情况下它可能是好的,因为在这种情况下,目录路径最可能包含一个或多个环境变量引用,它们必须是在拥有真实的目录路径之前扩展。

在示例D:\OneDrive - Business中第二个空格/制表符分隔的字符串之后的空格/制表符后面的字符串应该被分配,而不会在空格/制表符上进一步拆分以循环变量C,因为{{1在选项字符串*中的2之后。

第一个 IF 条件确保在Windows XP上处理正确的行, REG 的输出以一个标题开始,其中只跳过第一行。< / p>

第二个 IF 条件可确保用户文件夹值具有非空值。

最终将感兴趣的字符串分配给环境变量tokens=1,2*,并退出 FOR 循环,跳转到标签UserFolder下方的命令。

如果在Windows注册表中找不到注册表值,则会执行 FOR 循环下面的命令。

要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。

  • UserFolderSet
  • echo /?
  • for /?
  • goto /?
  • if /?

另请阅读Microsoft有关Using Command Redirection Operators

的文章

答案 1 :(得分:0)

也许:

For /F "EOL=H Tokens=2*" %%A In ('Reg Query "HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Business1" /V "UserFolder"') Do Set "var=%%B"
Echo(%%var%% = %var%
Pause

答案 2 :(得分:0)

我不会使用文本文件但直接Reg.exe来读取注册表值

@Echo off
Set "Key=HKCU\SOFTWARE\Microsoft\OneDrive\Accounts\Business1"
Set "Val=UserFolder"
For /f "Tokens=2* delims= " %%A in (
  'Reg query "%Key%" /V %Val% ^|find /i "%Val%" '
) Do Set "%Val%=%%B"
Set %Val%

答案 3 :(得分:0)

您可以将[MSDN]: reg的输出与[MSDN]: findstr合并(以过滤掉一些无用的数据),并使用[SS64]: for迭代剩下的内容。

以下是代码(必须文件中运行):

@echo off

set _KEY_NAME=HKEY_CURRENT_USER\SOFTWARE\Microsoft\OneDrive\Accounts\Business1
set _VALUE_NAME=UserFolder
set _VALUE_DATA=

for /f "tokens=1,2,*" %%f in ('reg query %_KEY_NAME% /v %_VALUE_NAME% /t REG_SZ 2^>NUL ^| findstr %_VALUE_NAME%') do (
    set _VALUE_DATA="%%h"
)

echo Data: %_VALUE_DATA%

这是基于我的机器上的事实( Win10 ),reg query %_KEY_NAME% /v %_VALUE_NAME% /t REG_SZ _KEY_NAME _VALUE_NAME ),输出:

HKEY_CURRENT_USER\SOFTWARE\_DummyKey
    _DummyValue    REG_SZ    D:\OneDrive - Business
End of search: 1 match(es) found.

@ EDIT0 :在看了@Mofi的解决方案之后,我意识到我没有错误处理。添加了一些。