Background
I am attempting to sync files from my hard drive to my MEGA account (https://mega.nz/), a free encrypted online data storage service. Unfortunately, MEGA has not released any Windows command line utilities and their current Windows sync client (https://mega.nz/#sync) needs a lot of work. It deleted all my local files one time when I was attempting to upload. I was able to find some third-party utilities on GitHub called Megatools (https://megatools.megous.com/) that are severely lacking in their functionality. For example: the copy function does not give you the option of overwriting files on the MEGA server with newer versions from the hard drive. As such, I have sought to expand Megatools by writing a Windows Batch File program.
Windows Batch Sync Program
The program is pretty simple: it scans the local sync folder using FORFILES
(http://ss64.com/nt/forfiles.html) and then compares properties such as file name, relative path, size, and date modified against a listing of remote files. The remote files are quickly populated using the Megatools megals.exe
function. Properties are stored in arrays. Please note that I am aware of the fact that Windows batch files do not treat arrays like other programming languages do, that to the compiler it is simply another variable.
Problem
Because FORFILES
functions as a basic for loop, and I'm using indexed arrays to store information, I need to enable Delayed Expansion for the indexing to work as desired. I really don't understand Delayed Expansion very well. I've tried researching it a lot, but it doesn't make any sense to me. Since the syntax for Delayed Expansion involves encapsulating variables with !var!
instead of %var%
and my file names may contain a !
symbol, I'm at a loss as to what to do.
I researched the problem and apparently the solution is to temporarily disable Delayed Expansion using SETLOCAL DisableDelayedExpansion
and ENDLOCAL
statements, but that involves limiting the scope of any variables created using the SET
statement to lines between SETLOCAL
and ENDLOCAL
.
The one solution I found to this problem was to append ENDLOCAL
with & SET newvar=%oldvar%
but newvar
remains empty whenever I try to run the program!
Code (abridged)
@ECHO off
SETLOCAL EnableDelayedExpansion
REM ...
REM (Parameter processing code, irrelevant)
REM ...
SET localpathempty=UNSET
SET numlocal=UNSET
CALL:islocalpathempty
IF "%localpathempty%"=="FALSE" (
ECHO Items found in local directory. Gathering file names...
SETLOCAL DisableDelayedExpansion
FOR /F "tokens=*" %%a IN ('FORFILES /S /P "%localpath%." /C "cmd /c echo @FILE"') DO (
SET /A "j+=1"
SET "line=%%~a"
SETLOCAL EnableDelayedExpansion
SET localfilename[!j!]=!line!
ECHO Array Index inside 'LOCAL': !j!
ENDLOCAL
ECHO Array Index outside 'LOCAL': %j%
)
ENDLOCAL & SET numlocal=%j%
)
IF "%localpathempty%"=="TRUE" (
ECHO WARNING: LOCAL PATH %localpath% IS EMPTY. PROCESSING SKIPPED.
)
ECHO Final Index: %j%
ECHO Total Items: %numlocal%
REM ...
REM (Further processing of local files and remote files)
REM ...
ENDLOCAL
GOTO :eof
REM ...
REM (functions)
REM ...
Results
Items found in local directory. Gathering file names...
Array Index inside 'LOCAL': 1
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 2
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 3
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 4
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 5
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 6
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 7
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 8
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 9
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 10
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 11
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 12
Array Index outside 'LOCAL':
Array Index inside 'LOCAL': 13
Array Index outside 'LOCAL':
Final Index:
Total Items:
Question
As you can see, the index that is set before the second SETLOCAL EnableDelayedExpansion
statement does not survive that block of code. I need to be able to record that final index as well as the file name. I did not get so far as to try and pass the file name past the second SETLOCAL EnableDelayedExpansion
and ENDLOCAL
statements because the index doesn't even survive! Any help would be greatly appreciated with this problem. I realize my syntax may have some issues but I've done my best. The index disappearing is a huge mystery to me.
PS: If you're wondering why I'm starting with Delayed Expansion enabled instead of disabled, the reason is because the vast majority of the code that occurs later (not shown here) requires it to be enabled.