Tag Archive for 'Batch'

A Self-Sufficient Backup System

What is the reason for a document on backing up one’s data?  The reason is that this is a critical thing that one must get handled, out of the way, and automated in order to possess peace of mind while undertaking a comprehensive work involving data.  For years I have searched for a great piece of backup software.  I will share this great backup schematic and ensure it is in place on my own systems before tackling the first article on a place.

There are several backup solutions in the marketplace but most of them are not really backups in the tradition sense.  Microsoft’s One Drive, which is probably now the most popular is not a backup at all, but a transitioning of data to someone else’s computer in the first place.  The Acronis version that one obtains license to via purchasing a Western Digital hard drive constantly uses network activity, despite working as a local backup solution.  Others such as Veeam included end user license agreement clauses allowing them full on premise access for an audit any time they wish, at the customer’s expense.  Other cloud backup solutions require you to have an active subscription to their product and wait for a backup to restore, it it restores at all.    I once restored about 72 GB of data from a Spider Oak backup and it took almost a month. Jungle Disk was an excellent resource years ago, but they changed branding and shifted how they operated.   Amazon S3 is very cost effective but the software to use requires one to custom build the backup solution or trust someone else or someone’s software with their keys to Amazon web services.  The best backup software that I personally used was Evorim Advanced Backup, but it is only available in a fully-featured version for citizens of the European Union.

That brings us to what we want.  A differential backup solution using 7zip so that the files can be encrypted and stored on Dropbox (or other cloud option of one’s choosing).  The key aspects being encryption and differential backups so that one is not constantly reuploading their entire reference corpus every day.

This covers a differential backup scheme using 7Zip and Dropbox and it works on both Linux and Windows. With the Dropbox folder on a second hard drive, this scheme satisifies the 3-2-1 backup standard, which is three copies of the data, on two different media, with one offsite copy.

I initially had a backup scheme that created a zip archive and ran that file through openssl to create a new file with a .encrypted extension, that I uploaded to Amazon S3 or Dropbox for long term backups. The process was cumbersome and prone to inconvenience because I had to keep the decryption script somewhere so that I could remember the password and long command. Amazon S3 became more and more cumbersome over time due to needing to constantly update authentication schemes, login details, and the like that it became unreliable as a long term strategy for my needs. I am getting older and do not want to spend all my spare time troubleshooting, upgrading, and learning how redo things that were working perfectly the week before. It is also inconvienient to pass a lengthy filename to a script via a different script or by typing it into the command line. I finally settled on 7-Zip and Differential archives since the procedure works on both Windows and Linux with slight modifications to the paths and variables in the scripts. Windows uses / for path names, and Linux uses , and Batch files use %VAR% for variables, and Linux uses \${var} or \$var depending upon one’s mode and purpose.

The intial backup scheme is not as efficient as possible because it could be reduced to a single script that with a function that takes arguments, but that requires time that I have not devoted. On Windows three scripts are used. The first script is the backupcaller.bat. Backup caller uses a single argument, that argument being a 1 or a 0. Depending upon which argument is passed, the script then calls the full backup script, script0.bat, or it calls the differential backup script, script1.bat. A task exists to run *backupcaller 0* every three months. That creates a new full backup of the designated folders every three months. A task exists to run *backupcaller 1* every week. That creates a weeekly differential backup of the differences since the the last full backup.

The 7Zip command line for both the Windows and Linux versions of the scripts is the same. I will now discuss the Linux version.

The Linux version calls the fullbackup script every 90 days via cron job. It calls the differential backup script daily via a cron job. In Dropbox the full backups go into a folder named after the year, eg. backups/2025. The differential backups go into a folder named after the month, e.g. backups/2025-12 in the case of month 12. After the turn of the year, the old full backup will not be erased, and the new full backup will appear in backups/2026. I have a specific cronjob to run a full backup on 2026-01-01 so that I do not have to wait 90 days from the last full backup to get one for the year 2026.

In my case, I mount the dropbox folder in the home folder, but have it physically on a different drive. This satisfies the two media requirement in a 3, 2, 1 schema. User and mountpoint would need to be changed to reflect the actual username and path to the Dropbox folder, and CustomPasswordGoesHere should be changed to reflect an encryption password that one wishes to use long term.

#!/bin/bash

# This is a function to archive the files in an encrypted zip file on dropbox
fullarchive() {
unset IFS
OLD_IFS=$IFS && IFS=$'\n'
directory="/home/user/mountpoint/Dropbox/backups"
timestamp=$(date +"%Y-%m-%d-%H%M")
hostname=$(hostname)
year=$(date +"%Y")
month=$(date +"%m")
7z a -mm=Deflate -mfb=258 -mem=AES256 -p"CustomPasswordGoesHere" -mx9\
 ${directory}/${year}/"$1"-${hostname}-FULL-${year}.zip "$1"
IFS=$OLD_IFS
}

# NON HOME DIRECTORY LOCATIONS
cd /
fullarchive "etc"

# HOME DIRECTORY LOCATIONS
cd /home/user
fullarchive ".fonts"
fullarchive ".icons"
fullarchive ".themes"
fullarchive "Apps"
fullarchive "Data"
fullarchive "Dictionaries"
fullarchive "Documents"
fullarchive "Music"
fullarchive "Notes"
fullarchive "Pictures"
fullarchive "Scripts"
fullarchive "Server"
fullarchive "Templates"
fullarchive "Videos"

cd /home/user/.local/share

# contains customized .desktop files
fullarchive "applications"

cd /home/user
# contains Joplin media assets, among other things
fullarchive ".config"

The result of this script is a collection of encrypted zip files with names like *backups/2025/Documents-HOSTNAME-FULL-2025.zip* in folder based on the year in the Dropbox location. The metadata of the files can be viewed, but they cannot be extracted without the password.

If one is ultra paranoid, they could create a 99 character password with this script:

#!/bin/bash


long="$(openssl rand -base64 256)"
short="${long:0:100}"
echo "${short}"
# It becomes 99 characters because new line characters
# are removed to make it all one line when the output is on two lines.


From experience, such a password becomes annoying because I have had to extact from these zip files far more that I ever expected and that needs to factor into password selection. With a 99 character password, one must copy paste it for each extraction which means one must not lose some digital file with the password stored in it.

Now back to the differential portion of the backup.

#!/bin/bash


# This is a function to archive the files in an encrypted zip file on dropbox


diffarchive() {
unset IFS
OLD_IFS=$IFS && IFS=$'\n'
directory="/home/user/mountpoint/Dropbox/backups"
timestamp=$(date +"%Y-%m-%d-%H%M")
timestamp2=$(date +"%Y-%m-%d")
hostname=$(hostname)
year=$(date +"%Y")
month=$(date +"%m")
7z u ${directory}/${year}/"$1"-${hostname}-FULL-${year}.zip "$1"  -mm=Deflate -mfb=258 -mem=AES256 -p"CustomPasswordGoesHere" -mx9 -u- -up0q3r2x2y2z0w2!"${directory}/${year}-${month}/"$1"-${hostname}-Differential-${timestamp2}.zip"
IFS=$OLD_IFS
}


# NON HOME DIRECTORY LOCATIONS
cd /
diffarchive "etc"

# HOME DIRECTORY LOCATIONS
cd /home/user
diffarchive ".fonts"
diffarchive ".icons"
diffarchive ".themes"
diffarchive "Apps"
diffarchive "Data"
diffarchive "Dictionaries"
diffarchive "Documents"
diffarchive "Music"
diffarchive "Notes"
diffarchive "Pictures"
diffarchive "Scripts"
diffarchive "Server"
diffarchive "Templates"
diffarchive "Videos"

cd /home/user/.local/share

# contains customized .desktop files
diffarchive "applications"

cd /home/user
# contains Joplin media assets, among other things
diffarchive ".config"

This will create encrypted zip files in the monthly folder of the form *backups/2025-12/Documents-HOSTNAME-DIFFERENTIAL-2025-12-26.zip*. Most of the differentials will be tiny files since no files changed. In the event one changes a huge number of files, one could run another full backup for that folder only, or just allow the differentials to duplicate.

On my Linux machine, I run the differential backups daily because I realized after a Windows machine erasure that I had missed obtaining some data on it since the weekly differential had missed a massive data reorganization that I had done on my source code archives. That is a painful lesson as I had years of C# winforms projects.

The following cron runs the full backup scripts at 7:30 PM every 3 Months. It runs the differential backup script every day at 10:30 PM.

30 19 1 */3 * /home/username/scripts/fullbackup  
30 22 * * * /home/username/scripts/diffbackup

It is also imperative that one ensure they are not accidentaly overwriting a backup with an empty one via errors such as two of them labeled Documents. For my data organizations, I label source folders differently. For example, Linux source code is Linsource, and Windows source code is Winsource. That way, regardless of OS, I have a zip of each that I could open easily.

I did run into a problem with the Windows version, where some of the backups I thought I had were not present, because I set the filenames wrong and large archives were being overwritten with the wrong collections for backup to that name.

These solutions are not maximally efficient because I created them by hand just to get the job done. They could be reduced to a single script taking arguments, or more improved functions.

This is the set of Windows scripts, illustrated with only one folder called Pictures. To backup more folders than that, copy and paste the start line in backupcaller and change the filename to something else and specify the correct path.

REM ###################################################################
@echo off
REM Command enxtensions are enabled by default, but to ensure they are
REM working, it is set below.  This allows mkdir to create entire trees
SETLOCAL ENABLEEXTENSIONS

REM This is the script to call for the backups
REM This Edition: 20 July 2025
REM %1= type of backup, with 0 meaning full and 1 meaning diffrential


REM CALL the script for each folder for backup
REM the call keyword is necessary to run more than one script in a
REM sequence.  The start keyword will create a new process for each
REM script and run them all at the same time. Use either call or start

REM could do a simple for each folder script to get them all
REM && means execute the command if the one before was successful

REM PLACE FOLDERS ALPHABETICAL   DRIVE THEN FOLDER NAME
REM %1, 0=full backup 1=differential
REM ### C DRIVE USER FOLDER ###
start C:\Users\username\Scripts\admin\script%1.bat "Pictures-%COMPUTERNAME%-%USERNAME%-UsersDir" "C:\Users\username\Pictures"

In this script, backupcaller.bat, we are calling script%1.bat and passing two arguments to it. The first is to the filename of the zip file, and the second is the path to be compressed and encrypted. Once per quarter, this script is called by task scheduler via backupcaller.bat as the command and 0 as the argument.

backupcaller.bat 0

Which makes the start command insert a zero as follows.

start C:\Users\username\Scripts\admin\script0.bat "Pictures-%COMPUTERNAME%-%USERNAME%-UsersDir" "C:\Users\username\Pictures"

Here is script0.bat

REM ###################################################################
@echo off
REM Command enxtensions are enabled by default, but to ensure they are
REM working, it is set below.  This allows mkdir to create entire trees
SETLOCAL ENABLEEXTENSIONS

REM Name Full Backup Script
REM This Edition: 18 July 2025
REM %1= Folder Name to be used as the zip file name
REM %2= Folder Path to be archived

REM %1 %2 and %3 are like $1 $2 and $3 in Bash
REM create a timestamped zip file of a directory
REM ^ is a line continuation mark
FOR /F "TOKENS=1* DELIMS= " %%A IN (^
'DATE /T') DO SET CDATE=%%B
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN (^
'DATE /T') DO SET mm=%%B
FOR /F "TOKENS=1,2 DELIMS=/ eol=/" %%A IN (^
'echo %CDATE%') DO SET dd=%%B
FOR /F "TOKENS=2,3 DELIMS=/ " %%A IN (^
'echo %CDATE%') DO SET yyyy=%%B
for /f "tokens=1-3 delims=:." %%A in ("%time%") do (
    set hours=%%A
    set minutes=%%B
    set seconds=%%C)

REM -mhe=on for encrypting headers only works with 7-zip format, not zip

REM The date variable numbers differ from other scripts

SET date0=%yyyy%
SET date1=%yyyy%-%mm%
SET date2=%yyyy%-%mm%-%dd%
SET date3=%yyyy%-%mm%-%dd%-%hours%%minutes%

mkdir "D:\PathToDropboxFolderForZipFiles\%date0%"

REM CREATE THE FULL BACKUP ONCE PER QUARTER
REM TEST DATA:   Quicken  "C:\Users\username\Quicken"
REM script0.bat Quicken "C:\Users\username\Quicken"
REM mpass=15 is the maximum passes for max
REM mx9 is the maximum compression for max
REM "C:\Program Files\7-Zip\7z.exe" a -mm=Deflate -mfb=258 -mpass=15^
REM -mem=AES256 -p"AwsomePasswordGoesHere" -mx9^
REM "D:\PathToDropboxFolderForZipFiles\%date0%\%1-Full-%date0%.zip" %2
REM The above is the max compression of the much faster one below
REM the one below is insanely faster, to about an hour vs a day
"C:\Program Files\7-Zip\7z.exe" a -mm=Deflate -mfb=258^
 -mem=AES256 -p"AwsomePasswordGoesHere" -mx1^
 "D:\PathToDropboxFolderForZipFiles\%date0%\%1-Full-%date0%.zip" %2
endlocal
exit

The mx1 above could be as high as mx9. Those are the compression levels for zip files. The setting of mx1 is essentially store only, which makes the operation very quick, even for large amounts of data. Replace AwsomePassWordGoesHere with the encryption password that you want to use and remember for the future. In the Linux examples above, I used mx9 because after using it with large amounts of data for a while, it suits me to prioritize space savings rather than speed.
This will create a full backup of the form Pictures-computername-username-UsersDir-Full-2025.zip

Task scheduler calls using the argument of 1 for the days a differential backup is needed.

backupcaller.bat 1

script1.bat

REM ###################################################################
@echo off
REM Command enxtensions are enabled by default, but to ensure they are
REM working, it is set below.  This allows mkdir to create entire trees
SETLOCAL ENABLEEXTENSIONS

REM Name Differential Script
REM This Edition: 18 July 2025
REM %1= Folder Name to be used as the zip file name
REM %2= Folder Path to be archived

REM %1 %2 and %3 are like $1 $2 and $3 in Bash
REM create a timestamped zip file of a directory
REM ^ is a line continuation mark
FOR /F "TOKENS=1* DELIMS= " %%A IN (^
'DATE /T') DO SET CDATE=%%B
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN (^
'DATE /T') DO SET mm=%%B
FOR /F "TOKENS=1,2 DELIMS=/ eol=/" %%A IN (^
'echo %CDATE%') DO SET dd=%%B
FOR /F "TOKENS=2,3 DELIMS=/ " %%A IN (^
'echo %CDATE%') DO SET yyyy=%%B
for /f "tokens=1-3 delims=:." %%A in ("%time%") do (
    set hours=%%A
    set minutes=%%B
    set seconds=%%C)

REM -mhe=on for encrypting headers only works with 7-zip format, not zip

REM The date variable numbers differ from other scripts

SET date0=%yyyy%
SET date1=%yyyy%-%mm%
SET date2=%yyyy%-%mm%-%dd%
SET date3=%yyyy%-%mm%-%dd%-%hours%%minutes%

mkdir "D:\PathToDropboxFolderForZipFiles\%date0%"
mkdir "D:\PathToDropboxFolderForZipFiles\%date1%"

REM CREATE THE FULL BACKUP ONCE PER QUARTER
REM TEST DATA:   Quicken  "C:\Users\user\Quicken"
REM q1script0.bat Quicken "C:\Users\user\Quicken"
REM mpass=15 is the maximum passes for max
REM mx9 is the maximum compression for max
REM "C:\Program Files\7-Zip\7z.exe" u^
REM "D:\PathToDropboxFolderForZipFiles\%date0%\%1-Full-%date0%.zip" %2^
REM -mm=Deflate -mfb=258 -mpass=15 -mem=AES256^
REM -p"AwsomePasswordGoesHere" -mx9^
REM -u- -up0q3r2x2y2z0w2!"D:\PathToDropboxFolderForZipFiles\%date0%\%1-Differential-%date0%.zip"
REM The above is the max compression of the much faster one below
REM the one below is insanely faster, to about an hour vs a day
"C:\Program Files\7-Zip\7z.exe" u^
 "D:\PathToDropboxFolderForZipFiles\%date0%\%1-Full-%date0%.zip" %2^
 -mm=Deflate -mfb=258 -mem=AES256^
 -p"AwsomePasswordGoesHere" -mx1^
 -u- -up0q3r2x2y2z0w2!"D:\PathToDropboxFolderForZipFiles\%date1%\%1-Differential-%date2%.zip"
endlocal
REM pause
exit

This wil will create a differential
Pictures-computername-username-UsersDir-Differential-2026-01-02.zip. To create this zip file, it will compare the contents of Pictures-computername-username-UsersDir-Full-2026 and only add the files that are new or updated. That is because of the arguments -up0q3r2x2y2z0w2! passed to 7Zip.

Weekly backups just add to the space, but you could add those by customizing scripts further, or setting asside every 7th daily backup. You can leave old months, and have monthly differential backups relative to the quarterly. 2026-02 differential backups will compare against the 2026-Full, and 2025-01 differential backups will not be erased until you erase them. Differential backups via this method will not work with split archives, so you must great one large zip file. Zip files are necessary rather than 7Z files because 7Z files do not maintain Linux permissions such as the executable status of a file or read and write permissions. Zip format maintains those permissions in Linux. For tens of gigabytes in data, the time difference between mx1 and mx9 on a single large can be numerous hours. In my case, mx1 takes about 15 minutes and mx9 takes an entire day with multiple CPU cores at high temperature. The space savings can hit around 30%. That amount may not be worth it, but on a 2.7 TB usable drive, 300 GB of additional space available because of higher compression becomes relevant eventually. With a terabyte free, saving disk space matters less, and completing the full backup in about 15 minutes works well.

For each new folder one creates that they want to backup, add it to the backup scripts. Either to backupcaller on Windows or fullbacup and diffbackup both on Linux. One may revise the scripts or improve it however they desire. One could use One Drive, iCloud, or another cloud storage. Dropbox works for my purposes.

Now that a backup schema is in place, one can seriously begin to create.

Thank you for reading this newsletter. Next on the schedule is a look at North Dakota.

Batch file with date and time for zipping

WinRAR offers great feature. It will create a zip file using a name mask.  That allows one to create a file with an excellent name via the right click menu.  Buying many WinRAR licenses becomes cost prohibitive.  This batch file will do the same thing using 7Zip on Windows. The batch file must be saved in the SendTo folder on Windows.  7Zip must be installed

@echo off
REM create a timestamped zip file of a directory
REM ^ is a line continuation mark
FOR /F "TOKENS=1* DELIMS= " %%A IN (^
'DATE /T') DO SET CDATE=%%B
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN (^
'DATE /T') DO SET mm=%%B
FOR /F "TOKENS=1,2 DELIMS=/ eol=/" %%A IN (^
'echo %CDATE%') DO SET dd=%%B
FOR /F "TOKENS=2,3 DELIMS=/ " %%A IN (^
'echo %CDATE%') DO SET yyyy=%%B
for /f "tokens=1-3 delims=:." %%A in ("%time%") do (
    set hours=%%A
    set minutes=%%B
    set seconds=%%C)

SET date2=%yyyy%-%mm%-%dd%_%hours%%minutes%
"C:\Program Files\7-Zip\7z.exe" a -tzip^
 C:\archives\%~n1_%date2%.zip %1
pause

This will save the zip filed in C:\archives\zips with a filename that consists of the original directory name and a timestamp of the form directoryname_2022-01-28_2212.zip. To use it, right click a directory, and choose SendTo –> TheBatchFileName. In my case, the file is named 7zipBackup.bat