Verzeichnisberechnung

19

Für diese Herausforderung erhalten Sie einen absoluten Pfad und einen "neuen" Pfad (der absolut oder relativ sein kann), und Sie müssen den endgültigen Pfad zurückgeben.

Zum Beispiel, wenn Ihr aktuelles Verzeichnis war /var/tmp/test:

my_diroder my_dir/ sollte zurückkehren/var/tmp/test/my_dir

../../my_dir sollte zurückkehren /var/my_dir

/my_dir/./ sollte zurückkehren /my_dir

../../../../../ sollte zurückkehren /

Um pedantischer zu sein:

  • Ein Verzeichnis ist eine nicht leere Zeichenfolge , bestehend aus alphanumerischen Zeichen und die Symbole -, _, oder.
  • Ein Pfad ist eine Liste von 0 oder mehr Verzeichnissen , die mit getrennt werden /. Ein absoluter Pfad beginnt mit a /, ein relativer Pfad nicht. Pfade können ein Ende enthalten /.

Sie müssen den zweiten Pfad unter Angabe des ersten Pfads "auflösen".

Der Lösungsprozess ist:

  1. Testen Sie, ob der zweite Pfad relativ ist. Wenn ja, fügen Sie die Verzeichnisse des absoluten Pfads an den Anfang des zweiten Pfads ein.
  2. Wenn eines der Verzeichnisse vorhanden ist .., entfernen Sie es und das vorhergehende Verzeichnis. Wenn es das erste Verzeichnis ist, entfernen Sie es einfach.
  3. Wenn eines der Verzeichnisse vorhanden ist ., entfernen Sie es.
  4. Geben Sie den endgültigen absoluten Pfad aus. Sie sollten kein Ende ausgeben /.

Sie müssen nicht mit falschen Eingaben umgehen. Die Befehle sollten funktionieren, unabhängig davon, ob die übergebenen Verzeichnisse tatsächlich auf Ihrem Computer vorhanden sind. Sie können davon ausgehen, dass alles ein Verzeichnis ist, auch wenn es eine Erweiterung hat.

Testfälle

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"
"/."          ""        -> "/"

Dies ist ein , also machen Sie Ihre Einsendungen so kurz wie möglich in Ihrer Lieblingssprache!

Nathan Merrill
quelle
Einige Antworten scheinen davon auszugehen, dass Dateien (oder Symlinks) mit demselben Namen wie ein Teil des Verzeichnisbaums) nicht auf dem Computer vorhanden sind. Ist das erlaubt
Dennis
Können wir die beiden Eingaben in beliebiger Reihenfolge vornehmen?
Downgoat
Dumme Frage ... kann ich Nebenwirkungen haben? Speziell Nebenwirkungen wie, ähm, mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(oder so)?
Katze
@dennis. Die Ausgabe der Programme sollte unabhängig vom Dateisystem sein
Nathan Merrill
@ Downgoat das ist in Ordnung
Nathan Merrill

Antworten:

7

Retina , 44 Bytes

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

^$
/

Es wird erwartet, dass die Eingabe die zwei Pfade sind, die durch ein einzelnes Leerzeichen getrennt sind.

Probieren Sie es online! (Die erste Zeile aktiviert eine durch Zeilenvorschub getrennte Testsuite.)

Martin Ender
quelle
3

Python, 53 Bytes

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

Batch, 282 281 279 276 Bytes

@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

Ärgerlicherweise mögen Batch-Ausdrücke im Allgemeinen keine leeren Variablen. Bearbeiten: 1 Byte dank @ CᴏɴᴏʀO'Bʀɪᴇɴ und 2 Byte dank @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ gespeichert (und eine Reihe von Bytes auch bei anderen Antworten, obwohl leider nicht im Abspann).

Neil
quelle
Ich denke, Sie können ein Leerzeichen zwischen callund entfernen : x`, nein?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Huh, also kannst du. Ich habe eine Reihe von Antworten, die in diesem Fall aktualisiert werden müssen ...
Neil
2

Python 2, 265 260 254 Bytes

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)
Akrolith
quelle
1

Python, 142 137 Bytes

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])
orlp
quelle
1

Bash, 41 Bytes

Dieses Bash-Skript hat den Nebeneffekt, dass Verzeichnisse erstellt werden, wenn sie nicht vorhanden sind. Es sollte jedoch die Anforderungen erfüllen. Vielen Dank an Karl und Neil für eure Verbesserungen.

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

Verwendung: bash getpath.sh "absolute" "new"

Wenn Ihnen das stderr nicht gefällt, wenn das zweite Argument eine leere Zeichenfolge ist, können Sie es wie folgt testen (48 Byte):

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

Vorheriger 30-Byte-Versuch (es müssen Verzeichnisse vorhanden sein): cd $ 1; [$ 2] && cd $ 2; echopwd

Bryn
quelle
Die Frage lautet: Die Befehle sollten funktionieren, ob die übergebenen Verzeichnisse tatsächlich auf Ihrem Computer vorhanden sind.
Dennis
Ah ich sehe. Schade.
Bryn
Hallo und willkommen bei PPCG! Wenn Ihre Antwort nicht funktioniert, löschen Sie sie normalerweise. Sie können auf den Link zum Löschen über diesem Kommentar klicken.
NoOneIsHere
Sie könnten mkdir -psicherstellen, dass sie existieren.
Karl Napf
Danke, ich versuche eine Version mit mkdir. Ich werde diese Antwort löschen und eine neue hinzufügen, wenn ich es herausfinde.
Bryn
1

C # 43 Bytes

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

1 Byte dank @aloisdg gespeichert

Path.Combinefasst die Argumente zusammen und Path.GetFullPathlöst das ..\s auf

jlynch630
quelle
Hallo und willkommen bei PPCG! Dies ist kein gültiges Programm - entweder include mainund eine Klasse oder ändern Sie es in ein lanbda: a,b->...
NoOneIsHere
Ich wollte es posten :) Schöne erste Einreichung! Sie können das Leerzeichen nach dem entfernen ,: (x, y)=>(x,y)
Aloisdg sagt Reinstate Monica
Auch die C # -Tipps für Golffäden könnten Sie interessieren.
Aloisdg sagt Reinstate Monica
1

Knoten REPL, 8 - 12 Bytes

path.resolve

Zum Glück müssen Sie require()in der REPL keine Standardmodule verwenden.

Test Suite

https://repl.it/Cclo/1

(Wenn die Ausgabe am Ende ist true, stimmt sie überein)

Patrick Roberts
quelle
1

Javascript, 210 Bytes

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)}

Hier ist die Testsuite

Mit Zeilenumbrüchen anstelle von Semikolons:

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)
}
CShark
quelle
0

Java 7, 83 Bytes

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

normalizewird benötigt, um mit relativen Referenzen umzugehen. addwird verwendet, um den zweiten Pfad zu behandeln /, der Paths.get(a, b)nicht wie angegeben behandelt wird.

jaxad0127
quelle
Hallo und willkommen bei PPCG! Dies ist ein guter erster Beitrag!
NoOneIsHere
0

Bash, 38 Bytes

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

Erfordert keine Root-Rechte und macht keine Annahmen über vorhandene oder nicht vorhandene Dateien, Verzeichnisse oder symbolische Links.

Teste es auf Ideone .

Wie es funktioniert

[[ $2 = /* ]]testet, ob das zweite Befehlszeilenargument mit beginnt /.

Ist dies nicht der Fall, ist der Pfad relativ und p=$1setzt die Variable p auf das erste Befehlszeilenargument.

Auf diese Weise $p/$2ist /$2if $2ein absoluter und $1/$2ein realistischer Pfad.

Zum Schluss wird realpath -sm $p/$2der kanonische absolute Pfad von gedruckt $p/$2. Der -sSchalter veranlasst Realpath , symbolische Verknüpfungen zu ignorieren, und dem -mSchalter fehlen Komponenten.

Dennis
quelle
0

Ruby, 16 Bytes

Da anscheinend die Verwendung einer Methode aus der Standardbibliothek erlaubt ist:

File.expand_path

Sehen Sie sich die Test - Suite auf repl.it .

Jordan
quelle
Die Eingabe über Variablen ist nicht zulässig, aber die File.expand_path
Nathan Merrill
Ich würde auch empfehlen, es tatsächlich mit der Testsuite zu testen, um sicherzustellen, dass es in allen Testfällen ordnungsgemäß funktioniert.
Nathan Merrill
@ NathanMerrill Ich habe, aber ich werde weitermachen und etwas auf repl.it kleben.
Jordanien
Bearbeitet, um den Link zur Testsuite einzuschließen.
Jordanien
0

GNU sed , 81 59 + 1 = 60 Bytes

+1 Byte für -rFlag. Erwartet, dass die Eingabe in STDIN durch ein einzelnes Leerzeichen getrennt wird.

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

Probieren Sie es online!

Erläuterung

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
Jordan
quelle
0

Zsh , 15 Bytes

a=$1/$2
<<<$a:a

Der :aModifikator macht genau das.

Probieren Sie es online!

GammaFunktion
quelle