2012-11-05 136 views
0

我有兩個絕對文件路徑(AB)。我想用B的相對路徑轉換A。我如何使用Lua腳本來做到這一點?如何使用LUA轉換相對路徑中的絕對路徑?

+1

如果您提供了'A'和'B'以及您想要的輸出示例,那麼您的問題就會變得更加清晰。 – millimoose

+0

你問是否有一個特定的功能來做到這一點,或者你是否要求在Lua中實現它的算法? –

回答

3

的算法要做到這一點是:

  1. 都轉換路徑,以規範形式。 (即從文件系統根目錄開始,沒有結尾斜槓,沒有雙斜槓等)
  2. 從兩個路徑中刪除它們的公共前綴。 (例如,從A="https://stackoverflow.com/a/b/c/d.txt" B="https://stackoverflow.com/a/b/e/f.txt"A="c/d.txt" B="e/f.txt"
  3. 通過路徑分隔符拆分剩餘的路徑。 (所以你最終會得到A={"c", "d.txt"} B={"e", "f.txt"}
  4. 如果原路徑B指向一個普通文件,刪除B的最後一個元素,如果它指向一個目錄,保持原樣(對於我們的例子,得到B={"e"}
  5. 左B中每一個項目,在A開頭插入一個..(與A={"..", "c", "d.txt"}
  6. 得到的使用路徑分隔符來獲得最終的結果加入的A內容:"../c/d.txt"

這是一個非常粗糙的實現,它可以在沒有庫的情況下工作。它不處理任何邊界情況,如fromto是相同的,或者一個是另一個的前綴。 (通過這個我的意思是功能肯定會在這些情況下打破,因爲mismatch將等於0。)這主要是因爲我很懶;也是因爲代碼已經變得有點長,這會更多地損害可讀性。

-- to and from have to be in a canonical absolute form at 
-- this point 
to = "https://stackoverflow.com/a/b/c/d.txt" 
from = "https://stackoverflow.com/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 
+0

非常感謝! – user1798951

1

使用pl.path.relpath從筆形電筒庫(doc/source)。

+0

使用現有的實現是一個好主意,但它似乎依賴於['lfs'](http://keplerproject.github.com/luafilesystem/),這是一個二進制擴展。這可能是也可能不是一個問題 - 不知道有多麼棘手或者不在本機擴展中使用他們的應用程序 - 對於OP。 – millimoose

+0

是的,LFS是一個頻繁的要求,但我應該降低它,謝謝你這樣做;) – catwell