동적 연결 디렉터리

동적 연결 디렉터리

동적으로 업데이트되는 링크를 만들 수 있는 방법이 있습니까? 내 구체적인 상황은 여러 개의 연습(디렉토리)이 있고 최신 연습에 연결하고 싶다는 것입니다.

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

그래서 내가 cd exercises/exercise_latest항상 최신 항목으로 이동합니다. 새 디렉토리를 추가하면 exercise_04링크가 대신 해당 디렉토리를 가리키게 됩니다.

제가 생각해 낼 수 있는 해결책은 다음과 같습니다.

  1. 1분에 한 번씩 실행되고 새 디렉터리를 감지하면 다시 연결하는 크론 작업입니다.
  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.

이것은 완벽한 솔루션은 아니지만 매우 안정적으로 작동하며 매우 비효율적이지는 않습니다.

관련 정보