Skróć ścieżkę bezwzględną

17

Czasami długą ścieżkę bezwzględną, np. Parametr wiersza polecenia do narzędzia linux, można skrócić, używając bieżącego katalogu roboczego jako odniesienia:

$ pwd
/home/heh

$ cat /home/heh/mydir/myfile
my stuff

$ cat mydir/myfile
my stuff

W tym wyzwaniu powinieneś stworzyć funkcję lub program, który otrzyma dwa parametry:

  1. Ścieżka bezwzględna, w formacie linux (zaczyna się od /)
  2. Aktualny katalog, w tym samym formacie

Dane wyjściowe są krótsze z następujących:

  • Wejście 1 bez zmian
  • Ścieżka względna, która odnosi się do tego samego pliku / katalogu co ścieżka bezwzględna

Drobne punkty:

  • Jeśli twój system operacyjny jest zgodny z Linuksem, możesz użyć bieżącego katalogu systemu zamiast odbierać go jako dane wejściowe
  • Możesz założyć, że dane wejściowe zawierają tylko znaki alfanumeryczne (i separatory ścieżek)
  • Możesz założyć, że wejściowa ścieżka bezwzględna nie ma separatora ścieżek /na końcu
  • Możesz założyć, że wejściowy katalog bieżący ma separator ścieżek /na końcu
  • Nie można założyć, że ścieżka bezwzględna odnosi się do istniejącego pliku lub że jakakolwiek jego część jest katalogiem dostępnym; jednak bieżący katalog można uznać za prawidłowy
  • Możesz założyć, że nie ma żadnych dowiązań symbolicznych w pobliżu żadnej ze ścieżek - ponieważ nie chcę wymagać żadnego specjalnego sposobu radzenia sobie z dowiązaniami symbolicznymi
  • Nie ma potrzeby obsługi przypadku, w którym jedno z danych wejściowych jest katalogiem głównym
  • „Bieżący katalog” powinien być wyprowadzony jako .(pusty ciąg jest niepoprawny)

Przypadki testowe (wejście 1, wejście 2, wyjście):

/home/user/mydir/myfile
/home/user
mydir/myfile

/var/users/admin/secret/passwd
/var/users/joe/hack
../../admin/secret/passwd

/home/user/myfile
/tmp/someplace
/home/user/myfile

/dir1/dir2
/dir1/dir2/dir3/dir4
../..

/dir1/dir2
/dir1/dir2
.
anatolig
źródło
1
„Możesz założyć, że wejściowy katalog bieżący ma separator ścieżek /na końcu”. Jednak w twoich przykładach tak nie jest.
Kudłaty
1
Lubię to w ten sposób, ale niektórym podobają się w inny sposób
anatolyg
Blisko spokrewnione .
AdmBorkBork
Co powinno się stać, jeśli ścieżka bezwzględna i względna mają taką samą długość?
Dennis
1
Brakuje niektórych krytycznych przypadków testowych: /home/test /home/user/mydir/myfile /home/testoraz/a/b /a/b/d/e /a/b
Nathan Merrill,

Odpowiedzi:

7

Julia 0,5 , 32 bajty

!,~=relpath,endof
t->~t<~!t?t:!t

Wykorzystuje bieżący katalog roboczy jako bazę i obecnie nie można go przetestować na TIO.

Przykładowy przebieg

Ostrzeżenie: spowoduje to zmianę systemu plików.

$ sudo julia --quiet
julia> function test(target,base)
       mkpath(base)
       cd(base)
       shorten(target)
       end
test (generic function with 1 method)
julia> !,~=relpath,endof
(relpath,endof)

julia> shorten = t->~t<~!t?t:!t
(::#1) (generic function with 1 method)

julia> test("/home/user/mydir/myfile","/home/user")
"mydir/myfile"

julia> test("/var/users/admin/secret/passwd","/var/users/joe/hack")
"../../admin/secret/passwd"

julia> test("/home/user/myfile","/tmp/someplace")
"/home/user/myfile"

julia> test("/dir1/dir2","/dir1/dir2/dir3/dir4")
"../.."

julia> test("/dir1/dir2","/dir1/dir2")
"."

Wersja alternatywna, 35 bajtów (dyadyczna)

^,~=relpath,endof
t-b=~t<~t^b?t:t^b

To pobiera katalog podstawowy jako dane wejściowe, dzięki czemu można go przetestować bez modyfikowania systemu plików.

Wypróbuj online!

Dennis
źródło
Przedefiniowanie Base.-błędów, chyba że jest to wyraźnie zaimportowane, prawda?
Julian Wolf,
W wersji 0,5 może to oznaczać błąd, ale tylko jeśli użyjesz go -przed ponownym zdefiniowaniem. W wersji 0.4 wyświetla ostrzeżenie, czy używasz go przed redefinicją, czy nie.
Dennis
9

JavaScript (ES6), 107 106 bajtów

Bierze ścieżkę bezwzględną ai bieżącą ścieżkę cw składni curry (a)(c).

a=>c=>(A=a.split`/`,s='',c.split`/`.map(d=>!s&A[0]==d?A.shift():s+='../'),s+=A.join`/`)[a.length]?a:s||'.'

Przypadki testowe

Arnauld
źródło
Bardzo fajna sztuczka [a.length]! Czy mogę go pożyczyć, aby poprawić swoją odpowiedź na Node.js?
zeppelin,
@zeppelin Sure. Idź po to!
Arnauld
8

Siatkówka , 85 83 82 bajtów

1 bajt zapisany dzięki @MartinEnder

^(..+)(.*;)\1
%$2
(%?)(.*);(.*)
$1$3;$2
\w+(?=.*;)
..
%;/

;
/
.*//
/
%/?|/$

^$
.

Wypróbuj online!

Kritixi Lithos
źródło
5

ES6 (Node.js REPL), 56, 54, 46, 45 bajtów

  • Użyj pustego ciągu zamiast „.” oznacza bieżący katalog (na wejściu), -1 bajt
  • Pożyczył [f.length]sztuczkę z @ Arnauld za odpowiedź , -6 bajtów
  • Użyj bieżącego katalogu zamiast jawnego parametru katalogu, -2 bajty
  • Usunięto zbędne nawiasy, -2 bajty

Grał w golfa

f=>(r=path.relative("",f))[f.length]?f:r||"."

Test

> F=f=>(r=path.relative("",f))[f.length]?f:r||"."
[Function: F]

> F("/home/user/mydir/myfile")
'mydir/myfile'

> F("/var/users/admin/secret/passwd")
'../../admin/secret/passwd'

> F("/home/user/myfile")
'/home/user/myfile'

> F("/dir1/dir2")
'../..'

> F("/dir1/dir2")
'.'
zepelin
źródło
Czy nie zezwalamy na funkcje node.js?
Downgoat,
@Downgoat Javascript lambdas są powszechnie akceptowane, jako forma odpowiedzi, więc nie rozumiem, dlaczego Node.js powinien być traktowany inaczej.
zeppelin,
4

Python 2, 135 144 bajtów

i=0
a,c=input()
b,d=a.split('/')*(a!=c),c.split('/')
while b[:i+1]==d[:i+1]:i+=1
print'.'[i:]or min('/'.join(['..']*len(d[i:])+b[i:]),a,key=len)

Wypróbuj online!

Niby długo, ale chciałem zrobić rozwiązanie bez wbudowanych funkcji ścieżki.

Edycja: 9 bajtów dodanych do konta dla przypadku testowego dostarczonego przez Nathana Merrilla

ćpun matematyki
źródło
3

Zsh + realpath, 58 bajtów

r=`realpath -m --relative-to=$*`
(($#2<$#r))&&r=$2
echo $r

Wypróbuj online!

Wersja Bash, 62 bajty

r=`realpath -m --relative-to=$*`
((${#2}<${#r}))&&r=$2
echo $r

Wypróbuj online!

Dennis
źródło
Dlaczego nie opublikować go w dwóch różnych odpowiedziach? Każdy język ma znaczenie!
gaborsch
2

Python 3 - 53 bajty

Używanie os.path:

import os
lambda x:min(x,os.path.relpath(x),key=len)

Pełny program (61 bajtów):

import os
x=input();print(min(x,os.path.relpath(x),key=len))
matsjoyce
źródło
O, dobre punkty. Python jest teraz na czele, tak!
matsjoyce,
@anatolyg Ha, wiedziałem, że przegapiłbym przynajmniej jeden przypadek testowy ... 😒 Wszystko już naprawione.
matsjoyce,
1

PHP, 204 bajtów

[,$l,$p]=$argv;$z=($d=array_diff_assoc)($y=($w=explode)("/",$p),$x=$w("/",$l));$m=str_pad("",3*count($z)-1,"../");$j=join("/",$r=$d($x,$y));echo$l!=$p?strlen($u=$m&&$j?"$m/$j":$m.$j)<strlen($l)?$u:$l:".";

Przypadki testowe

Rozszerzony

[,$l,$p]=$argv;
$z=($d=array_diff_assoc)($y=($w=explode)("/",$p),$x=$w("/",$l));
$m=str_pad("",3*count($z)-1,"../");
$j=join("/",$r=$d($x,$y));
echo$l!=$p
    ?strlen($u=$m&&$j?"$m/$j":$m.$j)<strlen($l)
      ?$u
      :$l
    :".";

jeśli ../../zamiast tego of ../..dozwolone jest Wyjście , można je skrócić do 175 bajtów

[,$l,$p]=$argv;$z=($d=array_diff_assoc)($y=($w=explode)("/",$p),$x=$w("/",$l));echo$l!=$p?strlen($m=str_pad("",3*count($z),"../").join("/",$r=$d($x,$y)))<strlen($l)?$m:$l:".";
Jörg Hülsermann
źródło
0

C # - 66 bajtów

Korzystanie z wbudowanego programu .NET i wymuszanie prawidłowej ścieżki:

(f,t)=>f==t?".":new Uri("/"+t).MakeRelativeUri(new Uri("/"+f))+"";

Gdzie f, ta wyjście jest string.

Wypróbuj online!

aloisdg przenosi się do codidact.com
źródło