Mark Lenkner
Mark Lenkner

Reputation: 13

Setting a variable from a string inside a TXT file with a batch file

I'm attempting to create a batch file for my company's users to use to migrate files from their older 'personal folder' network share to our new OneDrive implementation.

The problem is, some of our users have change the default sync folder for OneDrive to whatever drive and path they wanted, instead of keeping the default (*c:\users\username*)...for example, the one I'm using to test my BAT file against is using:

D:\OneDrive - Business

However, it does still have to work when it contains more or less delimiters, like C:\OneDrive or C:\This Is Where I Foolishly Store Stuff.

At this point, I've tried using REG QUERY to output to a text file from the UserFolder key in the registry to get the path, and now I'm trying to extract this path FROM the text file in question and set it to a variable. The text file that is created looks like the following:

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

What I want to do is set the "D:\OneDrive - Business" to a variable to use in a scripted MOVE command.

My code is so awful, that I will refrain from posting it unless someone decides its necessary to answer my question.

I'm sure that for at least a DOZEN of you, this is child's play, so I would really appreciate any help that is provided me!!!

Thanks!!

Upvotes: 1

Views: 375

Answers (4)

CristiFati
CristiFati

Reputation: 41206

You can combine the output of the [MSDN]: reg with [MSDN]: findstr (to filter out some useless data), and iterate over what's left using [SS64]: for.

Here's the code (it must be run from a batch file):

@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%

This is based on the fact that on my machine (Win10), reg query %_KEY_NAME% /v %_VALUE_NAME% /t REG_SZ (with different values for the _KEY_NAME and _VALUE_NAME), output:

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

@EDIT0: After looking at @Mofi's solution, I realized that I had no error handling. Added some.

Upvotes: 0

Mofi
Mofi

Reputation: 49216

Here is one batch solution for this task:

@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%"

Better readable is this version doing exactly the same:

@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%"

The command FOR executes the command REG in a background command process with capturing its output written to handle STDOUT.

An error message output by REG to handle STDERR is suppressed by redirecting it to device NUL because of 2^>nul. The redirection operator > is escaped with caret character ^ which is necessary to interpret > first as literal character by Windows command interpreter on parsing the FOR command line. But later on execution of REG command line with 2>nul by FOR > is interpreted as redirection operator. An error message could occur if the registry value does not exist at all in Windows registry.

FOR processes each non empty line of captured output of REG command by splitting the line up into substrings (tokens) using space and tab as delimiter (default).

The option skip=1 instructs FOR to skip the first line of captured output.

The option tokens=1,2* instructs FOR that first space/tab delimited string being here value name UserFolder should be assigned to first loop variable A.

The second space/tab delimited string being here type REG_SZ should be assigned to loop variable B being the next character in ASCII table. Now it should be clear why loop variables are case-sensitive while environment variables are not case-sensitive. This loop variable is not further processed here although it might be good in case of type is REG_EXPAND_SZ instead of REG_SZ as in this case the directory path contains most likely also 1 or more environment variable references which must be expanded before having real directory path.

The string after the spaces/tabs after second space/tab delimited string being in your example D:\OneDrive - Business should be assigned without further splitting up on spaces/tabs to loop variable C because of * after 2 in options string tokens=1,2*.

The first IF condition makes sure the right line is processed as on Windows XP the output of REG starts with a header where only the first line would be skipped.

The second IF condition makes sure the user folder value has a non empty value.

The string of interest is finally assigned to environment variable UserFolder and the FOR loop is exited with a jump to the commands below label UserFolderSet.

The commands below the FOR loop are executed if the registry value was not found in Windows registry.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • for /?
  • goto /?
  • if /?
  • set /?

Read also the Microsoft article about Using Command Redirection Operators.

Upvotes: 1

user6811411
user6811411

Reputation:

I won't use a text file but directly Reg.exe to read the registry value

@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%

Upvotes: 0

Compo
Compo

Reputation: 38719

Perhaps:

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

Upvotes: 0

Related Questions