2012-11-05 2 views
0

У меня есть два абсолютных пути к файлу (A и B). Я хочу преобразовать A в относительный путь B. Как я могу это сделать с помощью сценария Lua?Как преобразовать абсолютный путь в относительный путь с помощью LUA?

+1

Ваш вопрос будет более ясным, если вы представили примеры 'A' и' B' и нужный вам результат. – millimoose

+0

Вы спрашиваете, есть ли какая-то конкретная функция, или вы просите алгоритм для ее достижения в Lua? –

ответ

3

алгоритм, чтобы сделать это было бы:

  1. Преобразовать оба пути к каноническому виду. (I., начиная с корня файловой системы, без косых черт, без двойных слэшей и т. Д.)
  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"

Вот очень грубая версия, которая работает без библиотек. Он не обрабатывает любые граничные случаи, такие как from и to, то же самое, или один из них является префиксом другого. (Под этим я подразумеваю, что функция , безусловно, сломает в тех случаях, потому что 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