
동적으로 업데이트되는 링크를 만들 수 있는 방법이 있습니까? 내 구체적인 상황은 여러 개의 연습(디렉토리)이 있고 최신 연습에 연결하고 싶다는 것입니다.
exercises/
│ exercise_01/
│ │ files ...
│ exercise_02/
│ │ files ...
│ exercise_03/
│ │ files ...
│ exercise_latest/ -> exercise_03/
그래서 내가 cd exercises/exercise_latest
항상 최신 항목으로 이동합니다. 새 디렉토리를 추가하면 exercise_04
링크가 대신 해당 디렉토리를 가리키게 됩니다.
제가 생각해 낼 수 있는 해결책은 다음과 같습니다.
- 1분에 한 번씩 실행되고 새 디렉터리를 감지하면 다시 연결하는 크론 작업입니다.
- 링크로 만들지 말고
cd
최신 디렉터리에 대한 스크립트로 만드세요. - 수동으로 유지 관리
두 솔루션 모두 특별히 우아하지는 않습니다. 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
.
이것은 완벽한 솔루션은 아니지만 매우 안정적으로 작동하며 매우 비효율적이지는 않습니다.