Nested IF Statements for batch

2019-09-21 01:35发布

问题:

I am currently trying to get a list of items saved from a profile on an old machine and then sent to the new machine and profile, being that the profile is the same.

On Windows 7 the location %AppData%\Microsoft\Sticky Notes stores the .snt for sticky notes. That location exists natively all the way to Windows 10 1511.

On Windows 10 1607 it has been moved to %LocalAppData%\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState" and changed toplum.sqlite`.

If you upgraded from anything earlier than Windows 10 1607 it will have made a Legacy folder with ThresholdNotes.snt in it and that will convert over to the plum.sqlite.

I am writing a nested .bat which will:

IF old sticky notes location on the new computer exists
    check for pulled .snt file, then copy over
ELSE
    check for pulled .snt file

IF new legacy location not exist
    create then copy and rename .snt to convert
ELSE
    copy,rename

IF old sticky notes location not exist
    then check for new .sqlite file
ELSE
    copy new file to new location

Otherwise say there are none detected.

But it seems I may be writing it wrong or something because I have placed a pause in the .bat but it just closes immediately when ran.

Here is the current Pull part where it retrieves the .snt or .sqlite. Variables first and then the actual action part.

REM Saves Users Sticky Notes
Set StickyNotes="%userprofile%\AppData\Roaming\Microsoft\Sticky Notes\StickyNotes.snt"
Set FlashStickyNotes="%~dp0%USERNAME%\StickyNotes"

REM Saves Users Sticky Notes From Win 10 1607+
Set StickyNotesWin10="%userprofile%\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\plum.sqlite"
Set FlashStickyNotesWin10="%~dp0%USERNAME%\StickyNotesWin10"


Title Pulling StickyNotes
if exist %StickyNotes% ( xcopy %StickyNotes% %FlashStickyNotes% /f /y ) ELSE if exist %StickyNotesWin10% ( 
xcopy %StickyNotesWin10% %FlashStickyNotesWin10% /f /y ) else Echo "No Sticky Notes Detected"

^^This part seems to work just fine and not have any problems

Here's the Push part and this is where I seem to have trouble but maybe its formatting? Variables first and then the actual action part.

REM Saves Users Sticky Notes
Set StickyNotes="%userprofile%\AppData\Roaming\Microsoft\Sticky Notes\"
Set FlashStickyNotes="%~dp0%USERNAME%\StickyNotes\StickyNotes.snt"

REM Saves Users Sticky Notes From Win 10 1607+
Set StickyNotesWin10="%userprofile%\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\"
Set FlashStickyNotesWin10="%~dp0%USERNAME%\StickyNotesWin10\plum.sqlite"

Title Pushing StickyNotes
REM if old sticky notes location on the new computer exists, then check for pulled .snt file, then copy over ELSE
REM if new sticky notes location exists, check for pulled .snt file, if new legacy location not exist, then create and then copy and rename .snt to convert, else copy,rename
REM if old sticky notes location not exist, then check for new .sqlite file, if exist then copy new file to new location ELSE
REM otherwise say there are none detected
IF exist "%userprofile%\AppData\Roaming\Microsoft\Sticky Notes\"( IF exist "%FlashStickyNotes%"( xcopy %FlashStickyNotes% %StickyNotes% /F /Y ) 
IF exist "%userprofile%\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\"(
    IF exist "%FlashStickyNotes%"(
        IF not exist "%userprofile%\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\Legacy"(
            mkdir "%userprofile%\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\Legacy"
            xcopy %FlashStickyNotes% "%userprofile%\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\Legacy\ThresholdNotes.snt" /F /Y
        ) else IF exist "%userprofile%\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\Legacy"((
            xcopy %FlashStickyNotes% "%userprofile%\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\Legacy\ThresholdNotes.snt" /F /Y
        )
    )
) else IF not exist "%StickyNotes%" (
    IF exist %FlashStickyNotesWin10% (
    copy %FlashStickyNotesWin10% %StickyNotesWin10% /Y
    )
)
) ELSE Echo "No Sticky Notes Detected" 

回答1:

REM OS before Vista have no LocalAppData variable
if not defined LocalAppData set "LocalAppData=%AppData%\..\Local"

REM Saves Users Sticky Notes
Set StickyNotes=%AppData%\Microsoft\Sticky Notes\StickyNotes.snt
Set FlashStickyNotes=%~dp0%USERNAME%\StickyNotes

REM Saves Users Sticky Notes From Win 10 1607+
Set StickyNotesWin10=%LocalAppData%\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\plum.sqlite
Set FlashStickyNotesWin10=%~dp0%USERNAME%\StickyNotesWin10


Title Pulling StickyNotes
if exist "%StickyNotes%" (
    xcopy "%StickyNotes%" "%FlashStickyNotes%" /f /y
) else if exist "%StickyNotesWin10%" (
    xcopy "%StickyNotesWin10%" "%FlashStickyNotesWin10%" /f /y
) else Echo "No Sticky Notes Detected"

That is the Pull part. Just changed paths with quoting and use of std variables. Add %LocalAppData% not defined check if needed and use a substitute on OS before Vista.

REM OS before Vista have no LocalAppData variable
if not defined LocalAppData set "LocalAppData=%AppData%\..\Local"

REM Saves Users Sticky Notes
Set StickyNotes=%AppData%\Microsoft\Sticky Notes
Set FlashStickyNotes=%~dp0%USERNAME%\StickyNotes\StickyNotes.snt

REM Saves Users Sticky Notes From Win 10 1607+
Set StickyNotesWin10=%LocalAppData%\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState
Set FlashStickyNotesWin10=%~dp0%USERNAME%\StickyNotesWin10\plum.sqlite

Title Pushing StickyNotes
REM if old sticky notes location on the new computer exists, then check for pulled .snt file, then copy over ELSE
REM if new sticky notes location exists, check for pulled .snt file, if new legacy location not exist, then create and then copy and rename .snt to convert, else copy,rename
REM if old sticky notes location not exist, then check for new .sqlite file, if exist then copy new file to new location ELSE
REM otherwise say there are none detected
IF exist "%StickyNotes%" (
    IF exist "%FlashStickyNotes%" (
        xcopy "%FlashStickyNotes%" "%StickyNotes%" /F /Y
    )
) else IF exist "%StickyNotesWin10%\" (
    IF exist "%FlashStickyNotes%" (
        IF not exist "%StickyNotesWin10%\Legacy" (
            mkdir "%StickyNotesWin10%\Legacy"
            xcopy "%FlashStickyNotes%" "%StickyNotesWin10%\Legacy\ThresholdNotes.snt" /F /Y
        ) else (
            xcopy "%FlashStickyNotes%" "%StickyNotesWin10%\Legacy\ThresholdNotes.snt" /F /Y
        )
    )
) else (
    IF exist "%FlashStickyNotesWin10%" (
        copy "%FlashStickyNotesWin10%" "%StickyNotesWin10%" /Y
    ) else (
        Echo "No Sticky Notes Detected"
    )
)

Literal paths replaced with variables where suitable. Indenting made consistent so opening and closing braces can be paired easier. Replaced obsolete else if checks with just else.

Quoting paths done later as allows extending paths if needed.

Unsure if you exit from the script if Echo "No Sticky Notes Detected". If you do want to exit then can use:

>&2 Echo "No Sticky Notes Detected"
exit /b 1

so the echo goes to stderr and exit with errorlevel 1.

Code is not tested so please check my changes.



回答2:

Besides the syntax issues you have (missing SPACE between the conditional expression and the opening parenthesis, if exist "%somepath%" (; and even two opening parentheses once, if exist "%somepath%"((), I believe your problem is the logic and the misleading way of indentation and parenthesising you are using.

Let us assume the following code snippet:

@echo off
set "X=" & set "Y="
set /P X="X="
set /P Y="Y="

if defined X if defined Y (
    echo X=%X%, Y=%Y%
) else echo X and/or Y is empty

What would you expect to be returned in case variable X is empty?

Let us take a look to the same code in function but differently written (skipping the variable definitions/prompts this time):

if defined X (
    if defined Y (
        echo X=%X%, Y=%Y%
    ) else (
        echo X and/or Y is empty
    )
)

You may now notice that nothing is returned in case of an empty variable X.

The fixed code might look like this:

if defined X (
    if defined Y (
        echo X=%X%, Y=%Y%
    ) else (
        echo Y is empty
    )
) else (
    echo X is empty, Y not checked
)