
有什麼方法可以建立動態更新的連結。我的具體情況是,我有多個練習(目錄),我想連結到最新的一個:
exercises/
│ exercise_01/
│ │ files ...
│ exercise_02/
│ │ files ...
│ exercise_03/
│ │ files ...
│ exercise_latest/ -> exercise_03/
所以如果我cd exercises/exercise_latest
它總是去最新的。新增目錄exercise_04
將使連結指向該目錄。
我能想到的解決方案是:
- 每分鐘執行一次並在偵測到新目錄時重新連結的 cron 作業。
- 不要讓它成為一個鏈接,而是一個
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
。
這不是一個完美的解決方案,但它工作得相當可靠,而且效率也不是超級低。