У меня есть два абсолютных пути к файлу (A
и B
). Я хочу преобразовать A
в относительный путь B
. Как я могу это сделать с помощью сценария Lua?Как преобразовать абсолютный путь в относительный путь с помощью LUA?
ответ
алгоритм, чтобы сделать это было бы:
- Преобразовать оба пути к каноническому виду. (I., начиная с корня файловой системы, без косых черт, без двойных слэшей и т. Д.)
- Из обоих путей удалите их общий префикс. (Например, перейти от
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"
) - Разделить оставшиеся пути разделителем путей. (Итак, вы закончите с
A={"c", "d.txt"} B={"e", "f.txt"}
- Если исходный путь
B
указывает на обычный файл, удалите последний элементB
. Если он указывает на каталог, оставьте его как есть. (В нашем примере вы получитьB={"e"}
) - для каждого элемента оставленный в B, вставьте
..
в начале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 = "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
Большое спасибо! – user1798951
Использование существующей реализации - отличная идея, но, похоже, библиотека зависит от ['lfs'] (http://keplerproject.github.com/luafilesystem/), которая является двоичным расширением. Это может быть или не быть проблемой - не уверен, как неудобно или не развертывать собственные расширения с их приложением - для OP. – millimoose
Да, LFS является частым требованием, но я должен был его уточнить, спасибо за это;) – catwell
Ваш вопрос будет более ясным, если вы представили примеры 'A' и' B' и нужный вам результат. – millimoose
Вы спрашиваете, есть ли какая-то конкретная функция, или вы просите алгоритм для ее достижения в Lua? –