Динамическое связывание каталогов

Динамическое связывание каталогов

Есть ли способ создать ссылку, которая будет динамически обновляться? Моя конкретная ситуация такова, что у меня есть несколько упражнений (каталогов), и я хочу сделать ссылку на последний:

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

так что если я cd exercises/exercise_latestвсегда перехожу к последнему. Добавление нового каталога exercise_04заставит ссылку указывать на него.

Решения, которые я могу предложить, следующие:

  1. Задание cron, которое запускается раз в минуту и ​​выполняет переподключение при обнаружении нового каталога.
  2. Не сделать ссылку, а скрипт, который cdпереходит в последний каталог.
  3. Поддержание вручную

Ни одно из решений не является особенно элегантным. 1.действительно неэффективно и потенциально слишком медленно. Я не могу копировать файлы в 2.. 3.сводит на нет цель.

Версионные релизы программного обеспечения делают что-то похожее. Например, python3всегда ссылаются на последнюю версию Python 3. Однако они, вероятно, обновляются каждый раз, когда устанавливается новая версия.

Могу ли я сделать что-то более элегантное, чем мои идеи?

решение1

Я решил эту проблему, создав launchctl / launchd агента, который может прослушивать файлы. Это специфично для macOS, но есть похожие решения для 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>

Это выполняет скрипт Python ( .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()

здесь LINK_ROOTSсодержатся все файлы, которые должны быть связаны. Все файлы, соответствующие корню ссылки с подчеркиванием и любыми числами после него, будут соответствовать, наибольший из них будет связан с корнем ссылки.

поэтому если LINK_ROOTS = ['exercise']величайшее из них будет связано вот так exercise -> exercise_04.

Это не идеальное решение, но оно работает достаточно надежно и не слишком эффективно.

Связанный контент