-1

I am writing a small script to make my customers easily backup they're data.
It is executed from an external drive to avoid letter issues, even if customer change those folders destination for another drive.

Everything goes well in the loop but for a reason that I can't explain, the loop stops after the third iteration and tell me that it is finished ...
I need it to be batch in order to be as simple as a double click for the elders.
Here it is, if a good soul can help me ?

So far : I have tried AI ... but they only add confusion on despair ;o) (AI my a** !!)
I have tried voodoo .. but I am not good enogh at it ...
I have tested all variables and they seemd fine ...

@echo off
setlocal enabledelayedexpansion

:: Define source variables (actual user folders paths from registry)
for /f "tokens=1,2*" %%A in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Desktop" 2^>nul') do set DeskDir=%%C
for /f "tokens=1,2*" %%A in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "Personal" 2^>nul') do set DocsDir=%%C
for /f "tokens=1,3*" %%A in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Pictures" 2^>nul') do set PicsDir=%%C
for /f "tokens=1,3*" %%A in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Music" 2^>nul') do set MusicDir=%%C
for /f "tokens=1,3*" %%A in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "My Video" 2^>nul') do set VidsDir=%%C
for /f "tokens=1,2*" %%A in ('reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "{374DE290-123F-4565-9164-39C4925E467B}" 2^>nul') do set DownDir=%%C

:: Define the array of folders to backup
set "folders[0]=!DeskDir!"
set "folders[1]=!DocsDir!"
set "folders[2]=!PicsDir!"
set "folders[3]=!MusicDir!"
set "folders[4]=!VidsDir!"
set "folders[5]=!DownDir!"

:: Get the drive letter of the external drive where the script is located
for %%a in ("%~dp0") do set external_drive=%%~dpa

:: Set the destination drive for backup (same as the external drive)
set destination=%external_drive%%username%

:: Perform an incremental backup using robocopy
for /l %%i in (0,1,2,3,4,5) do (
    set folder=!folders[%%i]!
    for %%F in ("!folder!") do set "folder_name=%%~nF"
    robocopy "!folder!" "%destination%\!folder_name!" /S /E /XA:SH /Z /R:0 /W:0 /XJD /XJF /XF *.tmp *.bak /XD $RECYCLE.BIN /XD "System Volume Information" /XO /TEE /NDL /NP /ETA
)
echo Incremental Backup completed.
pause
5
  • How does it 'make' your customers back up files? Surely it will only work if the customer executes the script and/or specifically connects the external drive. Also, if the default locations of Pictures, Music, and Videos, is inside Documents, then you're going to be making a lot of unnecessary duplicates, when you copy the entirety of Documents! Commented Mar 4, 2024 at 9:21
  • It is simple as a double click and for most of my customers which are elderly it is better than something they don't know the start of a tail about (french expression) most of them have windows 7, 8, 8.1 10 or 11 and it work fine with my previous script which is long as a day without bread (another french expression), I a trying to learn better ways to help. Commented Mar 4, 2024 at 18:18
  • Windows already has 'Backup' or in earlier vesions such as your stated v7, 'Windows Backup and Restore', which are very simple to use with a friendly GUI interface. There are also plenty of freeware tools to aid in performing such tasks, but I have no intention of showing favoritism to one here. The best way to help them is to test these solutions, and along with the customers own decisions on what they consider important, setup a backup schedule using that software. It is certainly better than subjecting vulnerable, computer illiterate, or elderly, customers to this abomination of a script. Commented Mar 4, 2024 at 18:44
  • Dear @compo, You are right in some ways but all the solutions you mentioned have what I consider flaws ... either it is automated and there for nobody checks if it works and/or forget that it is in place, or it is manual and in most case stored in proprietary format. You call this script abomination, I find it rich and usefull, I must mention that I am french and so are my customers for the most part. Thank you for your advice, the script on this page is an attempt to symplify my previous one ... you should see it ;o) Commented Mar 5, 2024 at 7:13
  • FYI, I have been working on computers for public customers for 25+ years. I use scripts when fixing, installing and configuring their machines, but have learned never to leave them on the units. It is just one more thing that they'll require 'free' support with. Like when their backup device is full and/or holds two identical copies of all ther pictures, music, and videos. Elderly customers are not redirecting those directories, or using OneDrive. Commented Mar 5, 2024 at 10:27

1 Answer 1

-1

The AI generated batch file code does not work because of for /l %%i in (0,1,2,3,4,5) do. The valid syntax for a for /L loop is explained by the usage help of the Windows command FOR output on running in a command prompt window for /?.

Most of the AI generated code does not make much sense at all. There are first assigned the folder paths to named environment variables. Next the folder paths are assigned to other environment variables with a naming scheme looking like an array of folder paths. Why are not assigned the folder paths directly to the environment variables which are used later? Then a horrible loop of wrong syntax is used for processing the array looking like environment variables. There is just a lot of unnecessary code making the task more complicated than necessary and let it fail if a folder path contains one or more exclamation marks or a folder path read from registry ends with a backslash, or a registry value could not be found at all.

There could be used the following batch file for the backup operation task:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "DestinationFolder=%~d0\%USERNAME%"
(for %%# in ("Desktop|Desktop" "Personal|Documents" "My Pictures,Pictures" "My Music|Music" "My Video|Videos" "{374DE290-123F-4565-9164-39C4925E467B}|Downloads") do for /F "tokens=1,2 delims=|" %%G in (%%#) do call :BackupFolder "%%G" "%%H") & goto EndBatch
:BackupFolder
set "SourceFolder="
set "ValueName=%~1"
if "%ValueName: =%" == "%ValueName%" goto SimpleQuery
for /F "skip=2 tokens=1-3*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "%ValueName%" 2^>nul') do if /I "%%I %%J" == "%ValueName%" if not "%%~L" == "" if "%%K" == "REG_SZ" (set "SourceFolder=%%~L") else if "%%K" == "REG_EXPAND_SZ" call set "SourceFolder=%%~L"
if not defined SourceFolder for /F "skip=2 tokens=1-3*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "%ValueName%" 2^>nul') do if /I "%%I %%J" == "%ValueName%" if not "%%~L" == "" if "%%K" == "REG_SZ" (set "SourceFolder=%%~L") else if "%%K" == "REG_EXPAND_SZ" call set "SourceFolder=%%~L"
goto CheckSource
:SimpleQuery
for /F "skip=2 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders" /v "%ValueName%" 2^>nul') do if /I "%%I" == "%ValueName%" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "SourceFolder=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "SourceFolder=%%~K"
if not defined SourceFolder for /F "skip=2 tokens=1,2*" %%I in ('%SystemRoot%\System32\reg.exe QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v "%ValueName%" 2^>nul') do if /I "%%I" == "%ValueName%" if not "%%~K" == "" if "%%J" == "REG_SZ" (set "SourceFolder=%%~K") else if "%%J" == "REG_EXPAND_SZ" call set "SourceFolder=%%~K"
:CheckSource
if not defined SourceFolder echo Folder path for %2 not found.& goto :EOF
echo(
echo Backup of %2 ...
if "%SourceFolder:~-1%" == "\" for %%I in ("%SourceFolder%.") do if "%%~nxI" == "" (set "SourceFolder=%%~fI\") else set "SourceFolder=%%~fI"
%SystemRoot%\System32\robocopy.exe "%SourceFolder%" "%DestinationFolder%\%~2" /E /ETA /NDL /NP /XA:SH /XD $RECYCLE.BIN /XD "System Volume Information" /XF *.bak *.tmp /XO /XJ /R:0 /W:0
goto :EOF
:EndBatch
echo(
echo Incremental backup completed.
echo(
endlocal
pause

The first two command lines define completely the required execution environment with:

  1. Command echo mode turned off.
  2. Command extensions enabled as required by the batch file.
  3. Delayed variable expansion disabled for processing also correct folder paths with one or more !.

The base destination folder path is defined as concatenation of the drive letter with colon of the batch file storage location and the name of the account of the current user. There could be used as third command line also:

set "DestinationFolder=%~dp0%USERNAME%"

That would create the user account related backups in a subdirectory of the batch file directory if the batch file is not in the root directory of the storage media.

The fourth command line results in processing five pairs of registry value name and destination folder name. A vertical bar not possible in a folder name is used as separator between the two names. Each string pair is split up by the for /F loop on same command line and passing the two names as arguments to the subroutine BackupFolder starting already on next line in the batch file. The additional command goto EndBatch after the unconditional command operator & results in the continuation of the batch file processing below the label :EndBatch after the first FOR loop finished processing the five string pairs.

The code for querying the folder path from the registry of the current user is described in full details in my answer on How to create a directory in the user's desktop directory? There must be two variants supported by this batch file because of some registry value names contain a space character.

Note: Run the following command line on Windows 10/11 in a command prompt window:

reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"

There is output among other lines the line:

!Do not use this registry key    REG_SZ    Use the SHGetFolderPath or SHGetKnownFolderPath function instead

Such a line is not output on running the command line with User Shell Folders instead of Shell Folders. There should be used preferred since more than 25 years the User Shell Folders registry key. The usage of SHGetFolderPath or SHGetKnownFolderPath is not easy possible in a batch file as being C++ library functions.

There is an information output for the user for which folder is currently running the backup process. This information could be enough, but the options used for ROBOCOPY results in lots of additional output during the copying of the files.

The batch file detects a missing registry value and informs the user about the missing path instead of running in an undefined behavior as the AI generated code. The batch file handles also folder paths with one or more & and I correct while the AI generated code fails on such uncommon but possible folder paths.

ROBOCOPY has a special interpreting regarding to a backlash in an argument string. If the character \ is left to one more \ or " than the following backslash respectively double quote character is interpreted as literal character. A backslash left to any other character is interpreted literally and not as escape character for the next character.

A folder path read from the registry can end with a backslash. That is not usual for the five processed folder paths but nevertheless possible. It is not possible to remove the backslash at the end of the source folder path if there is one because of the source folder path could be also the root directory of a drive like F:\ and just F: would reference the current directory on drive F: instead of the root directory of that drive. Please read the Microsoft documentation about Naming Files, Paths, and Namespaces for more details.

The used solution is appending one more backlash at the end of the source folder path if the source folder path ends with one or more backslashes and is the root directory of a drive. The source folder path is redefined otherwise with all backslashes at the end removed from the folder path.

The usage of "%SourceFolder%" on the ROBOCOPY command line works now even if the source folder path is the root directory of a drive.

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

  • call /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • pause /?
  • reg /?
  • reg query /?
  • robocopy /?
  • set /?
  • setlocal /?

Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded reg command line with using a separate command process started in background with %ComSpec% /c and the command line within ' appended as additional arguments.

See also:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.