2 つの絶対ファイル パス (A
およびB
) があります。A
の相対パスで変換したいB
。Luaスクリプトを使用してどのように行うことができますか?
質問する
2586 次
2 に答える
3
これを行うアルゴリズムは次のようになります。
- 両方のパスを標準形式に変換します。(つまり、ファイルシステムのルートから開始し、末尾のスラッシュや二重スラッシュなどはありません。)
- 両方のパスから、共通のプレフィックスを削除します。(例: から
A="/a/b/c/d.txt" B="/a/b/e/f.txt"
に移動A="c/d.txt" B="e/f.txt"
) - 残りのパスをパス区切り記号で分割します。(だからあなたはで終わるでしょう
A={"c", "d.txt"} B={"e", "f.txt"}
- 元のパス
B
が通常のファイルを指している場合は、 の最後の要素を削除しますB
。ディレクトリを指している場合は、そのままにしておきます。(私たちの例では、あなたは得るでしょうB={"e"}
) - B に残っているすべての項目について
..
、 の先頭に a を挿入しA
ます。(結果はA={"..", "c", "d.txt"}
) - パスセパレーターを使用してコンテンツを結合し
A
、最終結果を取得します。"../c/d.txt"
これは、ライブラリなしで動作する非常に大まかな実装です。from
とto
同じである、または一方が他方のプレフィックスであるなどのエッジケースは処理しません。(これは、が に等しくなるため、これらのケースでは関数が確実に壊れることを意味します。) これは主に、私が怠け者だからです。また、コードがすでに少し長くなっており、これにより可読性がさらに損なわれるためです。mismatch
0
-- to and from have to be in a canonical absolute form at
-- this point
to = "/a/b/c/d.txt"
from = "/a/b/e/f.txt"
min_len = math.min(to:len(), from:len())
mismatch = 0
print(min_len)
for i = 1, min_len do
if to:sub(i, i) ~= from:sub(i, i) then
mismatch = i
break
end
end
-- handle edge cases here
-- the parts of `a` and `b` that differ
to_diff = to:sub(mismatch)
from_diff = from:sub(mismatch)
from_file = io.open(from)
from_is_dir = false
if (from_file) then
-- check if `from` is a directory
result, err_msg, err_no = from_file:read(0)
if (err_no == 21) then -- EISDIR - `from` is a directory
end
result = ""
for slash in from_diff:gmatch("/") do
result = result .. "../"
end
if from_is_dir then
result = result .. "../"
end
result = result .. to_diff
print(result) --> ../c/d.txt
于 2012-11-05T01:13:48.410 に答える