Dynamische Verknüpfung von Verzeichnissen

Dynamische Verknüpfung von Verzeichnissen

Gibt es eine Möglichkeit, einen Link zu erstellen, der dynamisch aktualisiert wird? Meine spezielle Situation ist, dass ich mehrere Übungen (Verzeichnisse) habe und auf die neueste verlinken möchte:

exercises/
│   exercise_01/
│   │    files ...
│   exercise_02/
│   │    files ...
│   exercise_03/
│   │    files ...
│   exercise_latest/ -> exercise_03/

also wenn ich cd exercises/exercise_latestes tue, wird immer das neueste angezeigt. Wenn ich ein neues Verzeichnis hinzufüge, exercise_04wird der Link stattdessen auf dieses verweisen.

Die Lösungen, die mir einfallen, sind:

  1. Ein Cron-Job, der einmal pro Minute ausgeführt wird und eine neue Verknüpfung herstellt, wenn er ein neues Verzeichnis erkennt.
  2. Machen Sie daraus keinen Link, sondern ein Skript, das cdzum aktuellsten Verzeichnis führt.
  3. Manuelle Wartung

Keine der Lösungen ist besonders elegant. 1.ist wirklich ineffizient und möglicherweise zu langsam. Ich kann keine Dateien in kopieren 2.. 3.macht den Zweck zunichte.

Versionierte Software-Releases machen etwas Ähnliches. Sie verlinken beispielsweise python3immer auf die neueste Python 3-Version. Sie werden jedoch wahrscheinlich jedes Mal aktualisiert, wenn eine neue Version installiert wird.

Kann ich etwas tun, das eleganter ist als meine Ideen?

Antwort1

Ich habe das Problem gelöst, indem ich einen launchctl / launchd-Agenten erstellt habe, der Dateien abhören kann. Dies ist macOS-spezifisch, aber es gibt ähnliche Lösungen für Linux.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
http://www.apple.com/DTDs/PropertyList-1.0.dtd>
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.me.exercise_listener.plist</string>

    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/python3</string>
        <string>/path/to/exercises/.ln_monitor.py</string>
    </array>
    <key>WatchPaths</key>
    <array>
        <string>/path/to/exercises/</string>
    </array>
    <key>StandardOutPath</key>
    <string>/path/to/exercises/.ln_monitor.log</string>
    <key>StandardErrorPath</key>
    <string>/path/to/exercises/.ln_monitor.log</string>
</dict>
</plist>

Dies führt ein Python-Skript aus ( .ln_monitor.py)

#!/usr/bin/env python3

import os
import re
from pathlib import Path
import time


DIR = Path(os.path.dirname(os.path.realpath(__file__)))
LINK_ROOTS = ['exercise']
VERBOSE = True


def cprint(*args):
    if VERBOSE:
        print(*args)


def main():
    for root in LINK_ROOTS:
        regex = r'^' + root + r'_\d+$'
        matches = [
            directory for directory in DIR.iterdir()
            if directory.is_dir() and
            re.match(regex, directory.name)]
        match_link = DIR / root
        if matches:
            match = sorted(matches)[-1]
            cprint(f'link to {match.name}')
            if match_link.is_symlink():
                if match_link.resolve() == match:
                    cprint('is already linked')
                    continue
                match_link.unlink()
                cprint('unlinking')
                time.sleep(0.5)
            else:
                cprint('no link yet')
            match_link.symlink_to(match)
            cprint('linked')


if __name__ == '__main__':
    main()

Hier LINK_ROOTSstehen alle Dateien, die verlinkt werden sollen. Alle Dateien, die zu einem Linkstamm mit Unterstrich und eventuell dahinter stehenden Zahlen passen, werden gematcht, die größte davon wird zum Linkstamm verlinkt.

also wenn LINK_ROOTS = ['exercise']das Größte so verlinkt wird exercise -> exercise_04.

Dies ist keine perfekte Lösung, aber sie funktioniert ziemlich zuverlässig und ist nicht übermäßig ineffizient.

verwandte Informationen