<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Hierarchical backup wanted.]]></title><description><![CDATA[<p dir="auto">Ok, NPP has great backup feature that saves all your edits to a special dir. But it would be a bit difficult to browse there though same-named copies originated from various sources (many days later). For example I could edit different websites and style.css files on each of them.</p>
<p dir="auto">It would be extremely nice to have hierarchical backup system, when if I edit (it’s WinScp) C:\Users\User\AppData\Local\Temp\scp18702\var\www\lala\data\www\example.com\actions\channel.php<br />
and backup copy to be saved to<br />
%Backup-dir%/Drive-c/Users\User\AppData\Local\Temp\scp18702\var\www\lala\data\www\example.com\actions\channel.php</p>
<p dir="auto">Seems there’s no such a plugin?</p>
]]></description><link>https://community.notepad-plus-plus.org/topic/20813/hierarchical-backup-wanted</link><generator>RSS for Node</generator><lastBuildDate>Tue, 21 Jul 2026 22:43:25 GMT</lastBuildDate><atom:link href="https://community.notepad-plus-plus.org/topic/20813.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 01 Mar 2021 14:40:24 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Hierarchical backup wanted. on Thu, 30 Sep 2021 11:26:08 GMT]]></title><description><![CDATA[<p dir="auto">Here is another version that backup file before it’s being overwritten with new data and appends date/time of the last modification date of the original file (not current date of the backup)<br />
i.e. file <code>C:\blah\mycode.js</code> will be backed up as <code>D:\Backup\Notepad++\C\blah\mycode.js_20210928_221824.js</code><br />
It also works with network shares</p>
<pre><code>from os import makedirs
from os.path import split, splitext, exists, getmtime
from shutil import copyfile
from time import strftime, localtime
from re import sub
from Npp import *

def callback_FILEBEFORESAVE(args):

    backup_dir = "D:\\Backup\\Notepad++\\";             # backup directory, must have trailing slash

    _file = notepad.getBufferFilename(args['bufferID']) # get full path
    if not exists(_file):                               # new file?
        return

    with open(_file, "r") as f:                         # read data from file
      if f.read() == editor.getText():                  # only save if file was modified
        console.write(msg + "file unchanged, no backup created\n")
        return

    file = sub("^\\\\+", "",                            # remove \ at beginning of the path
           sub('[&lt;&gt;"|?*:]', "_",                        # just a precation, replace invalid characters with _
           sub("^([a-zA-Z]):", r"\1",                   # remove : after drive letter
           _file)))

    dir, file = split(file)                             # get directory and file
    filename, ext = splitext(file)                      # get filename and extension

    new_dir = backup_dir + dir + "\\";
    new_filename = filename + ext                       # original filename
    new_filename = new_filename + str(strftime("_%Y%m%d_%H%M%S", localtime(getmtime(_file)))) + ext; # append date/time and original extension

    if not exists(new_dir):
      try:
        makedirs(new_dir)
      except Exception as err:
        console.write(msg + str(err).replace("\\\\", "\\") + "\n")
        return

    try:
      copyfile(_file, new_dir + new_filename)
      console.write(msg + "saved as " + new_dir + new_filename + "\n")
    except Exception as err:
      console.write(msg + str(err).replace("\\\\", "\\") + "\n")


notepad.clearCallbacks([NOTIFICATION.FILEBEFORESAVE])
notepad.callback(callback_FILEBEFORESAVE, [NOTIFICATION.FILEBEFORESAVE])

msg = "[Auto backup] " # console message prefix
console.write(msg + "initialized\n")
</code></pre>
<p dir="auto">For easy managing it’s better to save this script as a separate file i.e <code>autobackup.py</code> in the same directory where <code>startup.py</code> is<br />
and at the end of <code>startup.py</code> add this line:</p>
<pre><code>import autobackup # script's filename without extension
</code></pre>
]]></description><link>https://community.notepad-plus-plus.org/post/70155</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/70155</guid><dc:creator><![CDATA[vanowm]]></dc:creator><pubDate>Thu, 30 Sep 2021 11:26:08 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Mon, 20 Sep 2021 14:13:11 GMT]]></title><description><![CDATA[<p dir="auto">I made  for my environment</p>
<p dir="auto">def callback_notepad_FILESAVED(args):<br />
curr_buffer_id = notepad.getCurrentBufferID()<br />
notepad.activateBufferID(args[‘bufferID’])<br />
p = notepad.getCurrentFilename()<br />
time_now = datetime.now().strftime(“%Y-%m-%d_%H-%M-%S”)<br />
# print(p)<br />
# m = re.match(‘([C-Z]):’, p, re.I)<br />
if True:<br />
# p1=p.replace(‘:’,‘/’).replace(os.sep,‘/’).replace(‘//’,‘/’)<br />
# backup_path = top_level_backup_dir + os.sep + ‘Drive-{}’.format(m.group(1)) + p[2:]<br />
# backup_path = top_level_backup_dir + os.sep + p1<br />
# backup_dir = backup_path.rsplit(os.sep, 1)[0]<br />
# if not os.path.isdir(backup_dir): os.makedirs(backup_dir)<br />
# if os.path.isdir(backup_dir): shutil.copy2(p, backup_path)<br />
top_level_backup_dir = ‘C:/temp/backup/’<br />
p=p.replace(os.sep,‘/’)<br />
pathLisr=p.split(‘/’)<br />
pat=‘/’.join(pathLisr[:-1])<br />
OriginalName=pathLisr[-1]<br />
ext=os.path.splitext(OriginalName)[1]<br />
new_name=os.path.splitext(OriginalName)[0]+time_now+ext<br />
backup_dir=top_level_backup_dir + pat.replace(‘:’,‘/’).replace(os.sep,‘/’).replace(‘//’,‘/’)<br />
new_name= backup_dir+‘/’+new_name<br />
if not os.path.isdir(backup_dir): os.makedirs(backup_dir)<br />
shutil.copyfile(p,new_name)<br />
#################################</p>
]]></description><link>https://community.notepad-plus-plus.org/post/69874</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/69874</guid><dc:creator><![CDATA[Moisey Oysgelt]]></dc:creator><pubDate>Mon, 20 Sep 2021 14:13:11 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Fri, 05 Mar 2021 14:26:56 GMT]]></title><description><![CDATA[<p dir="auto">Thanks, Alan!<br />
And a guy helped me out there, so below is my final variant. I add time to file names and shorten paths derived from WinScp editing of remote files.</p>
<pre><code>from Npp import notepad, NOTIFICATION
import os
import shutil
import re
from datetime import datetime

def callback_notepad_FILESAVED(args):
    curr_buffer_id = notepad.getCurrentBufferID()
    notepad.activateBufferID(args['bufferID'])
    p = notepad.getCurrentFilename()
    m = re.match('([C-Z]):', p, re.I)
    time_now = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
    if m:
        top_level_backup_dir = r'c:\temp\mybackups'
        backup_path = top_level_backup_dir + os.sep + 'Drive-{}'.format(m.group(1)) + p[2:] + '.' + time_now
        backup_path = re.sub(r"c\:\\temp\\mybackups\\Drive\-C\\Users\\User\\AppData\\Local\\Temp\\scp\d+", r'c:\\temp\\mybackups\\WinScp', backup_path)
        backup_dir = backup_path.rsplit(os.sep, 1)[0]
        if not os.path.isdir(backup_dir): os.makedirs(backup_dir)
        if os.path.isdir(backup_dir): shutil.copy2(p, backup_path)

notepad.callback(callback_notepad_FILESAVED, [NOTIFICATION.FILESAVED])
</code></pre>
]]></description><link>https://community.notepad-plus-plus.org/post/63626</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/63626</guid><dc:creator><![CDATA[teleslon2]]></dc:creator><pubDate>Fri, 05 Mar 2021 14:26:56 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Tue, 02 Mar 2021 17:03:47 GMT]]></title><description><![CDATA[<p dir="auto">Opps, there should by “c:\temp\mybackups\WinScp” as replacement string. But anyway, it prints the same after replacement.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/63457</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/63457</guid><dc:creator><![CDATA[teleslon2]]></dc:creator><pubDate>Tue, 02 Mar 2021 17:03:47 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Tue, 02 Mar 2021 16:56:41 GMT]]></title><description><![CDATA[<p dir="auto">That’s strange. I surely restarted it and not once. Ok, now it’s working (after inserting “print”, hmm…).<br />
Next, I’d like to shorten some paths but my regex didn’t match, could you please help?</p>
<pre><code>print (backup_path)
backup_path = re.sub(r"&lt;c\:\\temp\\mybackups\\Drive\-C\\Users\\User\\AppData\\Local\\Temp\\scp\d+&gt;", 'WinScp', backup_path)
</code></pre>
<p dir="auto">Prints<br />
c:\temp\mybackups\Drive-C\Users\User\AppData\Local\Temp\scp26772\home\admin\web<br />
before replacing.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/63456</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/63456</guid><dc:creator><![CDATA[teleslon2]]></dc:creator><pubDate>Tue, 02 Mar 2021 16:56:41 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Tue, 02 Mar 2021 13:08:18 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/teleslon2" aria-label="Profile: teleslon2">@<bdi>teleslon2</bdi></a> said in <a href="/post/63438">Hierarchical backup wanted.</a>:</p>
<blockquote>
<p dir="auto">Folder c:\temp\mybackups exists.</p>
</blockquote>
<p dir="auto">Oh, you did say this, so my comment about that doesn’t apply.  Sorry.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/63445</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/63445</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Tue, 02 Mar 2021 13:08:18 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Tue, 02 Mar 2021 13:04:15 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/teleslon2" aria-label="Profile: teleslon2">@<bdi>teleslon2</bdi></a></p>
<p dir="auto">Did you notice this line in the demo script?:</p>
<p dir="auto"><code>top_level_backup_dir = r'c:\temp\mybackups'</code></p>
<p dir="auto">Obviously you’d want to replace the path I used with the path you desire.</p>
<p dir="auto">Otherwise I suggest the “print” route that <a class="plugin-mentions-user plugin-mentions-a" href="/user/ekopalypse" aria-label="Profile: Ekopalypse">@<bdi>Ekopalypse</bdi></a> recommended.</p>
<p dir="auto">Saying “it doesn’t work” is fine but it doesn’t leave much room for help from someone not sitting right at your computer.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/63444</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/63444</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Tue, 02 Mar 2021 13:04:15 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Tue, 02 Mar 2021 10:31:45 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/teleslon2" aria-label="Profile: teleslon2">@<bdi>teleslon2</bdi></a></p>
<p dir="auto">Did you restart npp after creating your user <a href="http://startup.py" rel="nofollow ugc">startup.py</a>?<br />
A <code>print(m)</code> before the <code>if m</code> will print to the python script console.<br />
Can be opened via the menu.<br />
Just make sure you use the same indentation (tabs or spaces but not mixed) as the lines before and after.</p>
]]></description><link>https://community.notepad-plus-plus.org/post/63441</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/63441</guid><dc:creator><![CDATA[Ekopalypse]]></dc:creator><pubDate>Tue, 02 Mar 2021 10:31:45 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Tue, 02 Mar 2021 09:58:00 GMT]]></title><description><![CDATA[<p dir="auto">Sadly, it doesn’t work for me. Folder c:\temp\mybackups exists.  I’ve tried files on Z (mapped c:\xampp.…), on С - nothing appeared in mybackups folder.<br />
NPP 7.8 Windows 8.1<br />
Is it possible to print debug info there? My primary language is PHP, so I’m not so smart here…</p>
]]></description><link>https://community.notepad-plus-plus.org/post/63438</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/63438</guid><dc:creator><![CDATA[teleslon2]]></dc:creator><pubDate>Tue, 02 Mar 2021 09:58:00 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Mon, 01 Mar 2021 21:09:13 GMT]]></title><description><![CDATA[<p dir="auto">So it could be as simple as a script like what follows.</p>
<p dir="auto">Note that this script only considers files that are mapped to a local C: through Z: drive.<br />
Other (network) paths are possible, but for the point of illustration, that’s just an unnecessary complication.</p>
<p dir="auto">Also note that much more error checking and results reporting (presumably upon failure) could be done.</p>
<p dir="auto">Typically the lines of the script would be added to the user’s <a href="http://startup.py" rel="nofollow ugc">startup.py</a> file, so that it is transparently activated and sitting there waiting for user saves to happen, after Notepad++ initializes.</p>
<p dir="auto">Anyway, the script:</p>
<pre><code class="language-z"># -*- coding: utf-8 -*-

from Npp import notepad, NOTIFICATION
import os
import shutil
import re

def callback_notepad_FILESAVED(args):
    curr_buffer_id = notepad.getCurrentBufferID()
    notepad.activateBufferID(args['bufferID'])
    p = notepad.getCurrentFilename()
    m = re.match('([C-Z]):', p, re.I)
    if m:
        top_level_backup_dir = r'c:\temp\mybackups'
        backup_path = top_level_backup_dir + os.sep + 'Drive-{}'.format(m.group(1)) + p[2:]
        backup_dir = backup_path.rsplit(os.sep, 1)[0]
        if not os.path.isdir(backup_dir): os.makedirs(backup_dir)
        if os.path.isdir(backup_dir): shutil.copy2(p, backup_path)

notepad.callback(callback_notepad_FILESAVED, [NOTIFICATION.FILESAVED])
</code></pre>
]]></description><link>https://community.notepad-plus-plus.org/post/63431</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/63431</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Mon, 01 Mar 2021 21:09:13 GMT</pubDate></item><item><title><![CDATA[Reply to Hierarchical backup wanted. on Mon, 01 Mar 2021 14:47:09 GMT]]></title><description><![CDATA[<p dir="auto"><a class="plugin-mentions-user plugin-mentions-a" href="/user/teleslon2" aria-label="Profile: teleslon2">@<bdi>teleslon2</bdi></a></p>
<p dir="auto">To my knowledge, there’s no plugin to do such a thing.</p>
<p dir="auto">But, with the PythonScript plugin (or another scripting plugin) you can do pretty much anything you want.  You would set up a “notification” on the save event and then fire off some script code to make a copy of your file.</p>
<p dir="auto">If you’d be willing to use the PythonScript plugin, I’ll volunteer to put together a demo for you (it’s really not difficult).</p>
]]></description><link>https://community.notepad-plus-plus.org/post/63416</link><guid isPermaLink="true">https://community.notepad-plus-plus.org/post/63416</guid><dc:creator><![CDATA[Alan Kilborn]]></dc:creator><pubDate>Mon, 01 Mar 2021 14:47:09 GMT</pubDate></item></channel></rss>