Obliczanie katalogu


19

Za to wyzwanie otrzymasz ścieżkę bezwzględną i „nową” ścieżkę (która może być absolutna lub względna) i musisz zwrócić ostatnią ścieżkę.

Na przykład jeśli bieżący katalog to /var/tmp/test:

my_dirlub my_dir/ powinien wrócić/var/tmp/test/my_dir

../../my_dir powinien wrócić /var/my_dir

/my_dir/./ powinien wrócić /my_dir

../../../../../ powinien wrócić /

Aby być bardziej pedantycznym:

  • Katalog jest niepusty łańcuch składający się ze znaków alfanumerycznych i symboli -, _lub.
  • Ścieżka to lista 0 lub więcej katalogów oddzielonych za pomocą /. Ścieżka bezwzględna zaczyna się od /, ścieżka względna nie. Ścieżki mogą zawierać zakończenie /.

Musisz „rozwiązać” drugą ścieżkę, biorąc pod uwagę pierwszą ścieżkę.

Proces rozstrzygania jest:

  1. Sprawdź, czy druga ścieżka jest względna. Jeśli tak, wstaw katalogi ścieżki bezwzględnej na początek drugiej ścieżki.
  2. Jeśli którykolwiek z katalogów jest .., usuń go i poprzedni katalog. Jeśli jest to pierwszy katalog, po prostu go usuń.
  3. Jeśli którykolwiek z katalogów jest ., usuń go.
  4. Wyjście końcowej ścieżki bezwzględnej. Nie powinieneś wypisywać zakończenia /.

Nie musisz obsługiwać nieprawidłowych danych wejściowych. Polecenia powinny działać, niezależnie od tego, czy przekazane katalogi faktycznie istnieją na twoim komputerze. Możesz założyć, że wszystko jest katalogiem, nawet jeśli ma rozszerzenie.

Przypadki testowe

Absolute      New          Output
"/a/b/c"      "d"       -> "/a/b/c/d" 
"/a/b/c/"     "d"       -> "/a/b/c/d"
"/a/b/c/"     "d/"      -> "/a/b/c/d"
"/a/b/c"      "/d"      -> "/d"
"/a/b/c"      "/d/"     -> "/d"
"/../a/b/c/"  "d"       -> "/a/b/c/d"
"/a/../b/c/"  "d"       -> "/b/c/d"
"/a/b/../c"   "d"       -> "/a/c/d"
"/a/b/c/.."   "d"       -> "/a/b/d"
"/a/b/c/"     ".."      -> "/a/b"
"/a/b/c"      "../d"    -> "/a/b/d"
"/a/b/c"      "/../d"   -> "/d"
"/a/b/c"      ""        -> "/a/b/c"
"/a/b/c"      "."       -> "/a/b/c"
"/a/b/c"      "./d"     -> "/a/b/c/d"
"/a/b/c"      "/./d"    -> "/d"
"/a/b/c"      "d.txt"   -> "/a/b/c/d.txt"
"/a/b/c"      "d."      -> "/a/b/c/d."
"/a/b/c"      ".txt"    -> "/a/b/c/.txt"
"/a/b/c"      ".txt/d"  -> "/a/b/c/.txt/d"
"/a/b/."      "./././." -> "/a/b"
"/direc"      "tory"    -> "/direc/tory"
"/a-_.b/"     "__._-."  -> "/a-_.b/__._-."
"/a/b"        "../.."   -> "/"
"/a/b"        "../../.."-> "/"
"/a"          "../../.."-> "/"
"/"           ""        -> "/"
"/"           "a"       -> "/a"
"/.."         "a"       -> "/a"
"/."          ""        -> "/"

To jest , dlatego , aby Twoje zgłoszenia były jak najkrótsze w swoim ulubionym języku!


Niektóre odpowiedzi wydają się zakładać, że pliki (lub dowiązania symboliczne) o tej samej nazwie co dowolna część drzewa katalogów) nie istnieją na komputerze. Czy to jest dozwolone?
Dennis

Czy możemy przyjąć dwa dane wejściowe w dowolnej kolejności?
Downgoat

Głupie pytanie ... czy mogę mieć skutki uboczne? W szczególności efekty uboczne, takie jak, um mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(lub coś w tym rodzaju)?
kot

@dennis. Dane wyjściowe programów powinny być niezależne od systemu plików
Nathan Merrill

@ downgoat to w porządku
Nathan Merrill

Odpowiedzi:


7

Siatkówka , 44 bajty

+`.+ /| |/\.?/
/
+1`/?[^/]*/\.\.|/\.?$

^$
/

Dane wejściowe powinny być dwiema ścieżkami oddzielonymi pojedynczą spacją.

Wypróbuj online! (Pierwszy wiersz włącza pakiet testowy oddzielony od linii).


3

Python, 53 bajty

from os.path import*;p=lambda a,n:normpath(join(a,n))

3

Partia, 282 281 279 276 bajtów

@echo off
set a=\
set r=%~2
if "%r%"=="" set r=%~1
if not %r:~,1%==/ set r=%~1/%~2
for %%a in (%r:/= %)do call:x %%a
if not %a%==\ set a=%a:~,-1%
echo %a:\=/%
exit/b
:x
if %1==. exit/b
if not %1==.. set a=%a%%1\&exit/b
if not %a%==\ for %%a in (%a:~,-1%)do set a=%%~pa

Irytujące wyrażenia wsadowe na ogół nie lubią pustych zmiennych. Edycja: Zapisano 1 bajt dzięki @ CᴏɴᴏʀO'Bʀɪᴇɴ i 2 bajty dzięki @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ (i kilka bajtów także na inne odpowiedzi, choć niestety niewymienione w czołówce).


Myślę, że możesz usunąć spację między calli: x`, nie?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Huh, więc możesz. Mam mnóstwo odpowiedzi, które wymagają aktualizacji w tym przypadku ...
Neil

2

Python 2, 265 260 254 bajtów

y=lambda:[x for x in raw_input().split("/")if x!=""and x!="."]
a=y();n=y();m=len(a)-1
while m>0:
 if a[m]==".."and m>0:del a[m];del a[m-1];m-=1
 elif a[m]=="..":del a[m]
 m-=1
for i in n:
 if i==".."and len(a)>0:del a[-1]
 else:a+=i,
print"/"+"/".join(a)

1

Python, 142 137 bajtów

def p(a,n,r=[],S="/"):
 for s in[s for s in((n[:1]!=S)*a+S+n).split(S)if"."!=s and s]:e=s!="..";r=[s]*e+r[1-e:]
 return S+S.join(r[::-1])

1

Bash, 41 bajtów

Ten skrypt bash ma efekt uboczny tworzenia katalogów, jeśli nie istnieją, ale powinien spełniać wymagania. Dzięki Karl i Neil za twoje ulepszenia.

mkdir -p $1;cd $1;mkdir -p $2;cd "$2";pwd

Zastosowanie: bash getpath.sh „absolutny” „nowy”

Jeśli nie podoba ci się stderr, gdy drugi argument jest pustym łańcuchem, możesz go przetestować w następujący sposób (48 bajtów):

mkdir -p $1;cd $1;[ $2 ]&&mkdir -p $2&&cd $2;pwd

Poprzednia 30-bajtowa próba (wymaga istnienia katalogów): cd $ 1; [$ 2] && cd $ 2; echopwd


Pytanie brzmi : Polecenia powinny działać, niezależnie od tego, czy przekazane katalogi faktycznie istnieją na twoim komputerze.
Dennis

O, rozumiem. Szkoda
Bryn

Witaj i witaj w PPCG! Zwykle, jeśli twoja odpowiedź nie działa, usuwasz ją. Możesz kliknąć link usuwania powyżej tego komentarza.
NoOneIsHere

Możesz mkdir -pupewnić się, że one istnieją.
Karl Napf,

Dzięki, próbuję wersji z mkdir. Usunę tę odpowiedź i dodam nową, jeśli się zorientuję.
Bryn

1

C #, 43 bajty

(x,y)=>Path.GetFullPath(Path.Combine(x,y));

Zapisano 1 bajt dzięki @aloisdg

Path.Combinełączy argumenty i Path.GetFullPathrozwiązuje ..\s


Witaj i witaj w PPCG! To nie jest poprawny program - albo maindołącz i klasę, albo zmień go na lanbda: a,b->...
NoOneIsHere 16.07.16

Zamierzałem to opublikować :) Ładne pierwsze zgłoszenie! możesz usunąć spację po ,: (x, y)=>(x,y)
aloisdg mówi Przywróć Monikę



1

JavaScript, 210 bajtów

function p(a,b){d='.';e=d+d;s='/';t='split';u='splice';r=(b[0]===s?[]:a[t](s)).concat(b[t](s));for(i=0;i<r.length;r[i]===e&&r[u](i?i-1:i,i?2:1)?(i&&i--):i++)(!r[i]||r[i]===d)&&r[u](i,1)&&i--;return s+r.join(s)}

Oto pakiet testowy

Z podziałami linii zamiast średników:

function p(a,b) {
    d='.'
    e=d+d
    s='/'
    t='split'
    u='splice'

    r=(b[0]===s?[]:a[t](s)).concat(b[t](s))

    for(i=0;i<r.length;r[i]===e&&r[u](i?i-1:i,i?2:1)?(i&&i--):i++)
        (!r[i]||r[i]===d)&&r[u](i,1)&&i--

    return s+r.join(s)
}

0

Java 7, 83 bajty

String p(String a,String b){return Paths.get(a).resolve(b).normalize().toString();}

normalizejest potrzebny do radzenia sobie z referencjami względnymi. addsłuży do obsługi drugiej ścieżki zaczynającej się od /, która Paths.get(a, b)nie będzie obsługiwać zgodnie z opisem.


Witaj i witaj w PPCG! To dobry pierwszy post!
NoOneIsHere

0

Bash, 38 bajtów

[[ $2 = /* ]]||p=$1
realpath -sm $p/$2

Nie wymaga uprawnień administratora i nie przyjmuje żadnych założeń dotyczących istniejących lub nieistniejących plików, katalogów lub dowiązań symbolicznych.

Przetestuj na Ideone .

Jak to działa

[[ $2 = /* ]]sprawdza, czy zaczyna się drugi argument wiersza polecenia /.

Jeśli nie, ścieżka jest względna i p=$1ustawia zmienną p na pierwszy argument wiersza poleceń.

Tak $p/$2jest, /$2jeśli $2jest to ścieżka bezwzględna i $1/$2jeśli jest to ścieżka realna.

Na koniec realpath -sm $p/$2drukuje kanoniczną ścieżkę bezwzględną $p/$2. Do -sprzełącznika marki realpath ignorować łączy symbolicznych, i -melementy przełączające brakuje.


0

Rubinowy, 16 bajtów

Ponieważ najwyraźniej stosowanie metody ze standardowej biblioteki jest dozwolone:

File.expand_path

Patrz zestaw testowy na repl.it .


Wprowadzanie za pomocą zmiennych jest niedozwolone, ale przesyłanie funkcji jest, co oznacza, że ​​należy je skrócić do File.expand_path:)
Nathan Merrill

Poleciłbym również przetestowanie go na zestawie testów, aby upewnić się, że działa poprawnie na wszystkich testach.
Nathan Merrill,

@NathanMerrill Zrobiłem, ale pójdę naprzód i nakleję coś na repl.it.
Jordan

Edytowane, aby zawierało link do zestawu testów.
Jordan

0

GNU sed , 81 59 + 1 = 60 bajtów

+1 bajt dla -rflagi. Oczekuje, że dane wejściowe na STDIN są oddzielone pojedynczą spacją.

s:.+ /::
s:/? :/:
:
s:/$|[^/]+/+\.\.|\.(/|$):\1:
t
s:^/*:/:

Wypróbuj online!

Wyjaśnienie

s:.+ /::  # If the second argument starts with a slash, drop the first argument
s:/? :/:  # Join the first and second arguments with a slash, dropping duplicate slashes
:
  s:/$|[^/]+/+\.\.|\.(/|$):\1:  # Drop trailing slashes, resolve double and single dots
  t                             # If the above substitution was made, branch to :
s:^/*:/:  # Ensure output begins with a single slash

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.