Calcul du répertoire

19

Pour ce défi, vous recevrez un chemin absolu et un "nouveau" chemin (qui peut être absolu ou relatif), et vous devrez retourner le chemin final.

Par exemple, si votre répertoire actuel était /var/tmp/test:

my_dirou my_dir/ devrait revenir/var/tmp/test/my_dir

../../my_dir devrait revenir /var/my_dir

/my_dir/./ devrait revenir /my_dir

../../../../../ devrait revenir /

Pour être plus pédant:

  • Un répertoire est une chaîne non vide constitué de caractères alphanumériques et des symboles -, _ou.
  • Un chemin est une liste de 0 ou plusieurs répertoires , séparés par /. Un chemin absolu commence par a /, pas un chemin relatif. Les chemins peuvent inclure une fin /.

Vous devez "résoudre" le deuxième chemin, étant donné le premier chemin.

Le processus de résolution est le suivant:

  1. Testez si le deuxième chemin est relatif. Si tel est le cas, insérez les répertoires du chemin absolu au début du deuxième chemin.
  2. Si l'un des répertoires l'est .., supprimez-le ainsi que le répertoire précédent. S'il s'agit du premier répertoire, supprimez-le simplement.
  3. Si l'un des répertoires l'est ., supprimez-le.
  4. Sortez le chemin absolu final. Vous ne devez pas produire de fin /.

Vous n'avez pas besoin de gérer une entrée incorrecte. Les commandes devraient fonctionner, que les répertoires transmis existent ou non sur votre machine. Vous pouvez supposer que tout est un répertoire, même s'il a une extension.

Cas de test

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

Ceci est un , alors faites vos soumissions aussi courtes que possible dans votre langue préférée!

Nathan Merrill
la source
Certaines réponses semblent supposer que les fichiers (ou liens symboliques) portant le même nom que n'importe quelle partie de l'arborescence de répertoires) n'existent pas sur la machine. Est-ce permis?
Dennis
Pouvons-nous prendre les deux entrées dans l'ordre que nous souhaitons?
Downgoat
Question stupide ... puis-je avoir des effets secondaires? Plus précisément, des effets secondaires comme, euh, mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(ou quelque chose)?
cat
@dennis. La sortie des programmes doit être indépendante du système de fichiers
Nathan Merrill
@downgoat ça va
Nathan Merrill

Réponses:

7

Rétine , 44 octets

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

^$
/

L'entrée devrait être les deux chemins séparés par un seul espace.

Essayez-le en ligne! (La première ligne active une suite de tests séparés par un saut de ligne.)

Martin Ender
la source
3

Python, 53 octets

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

Lot, 282 281 279 276 octets

@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

Les expressions batch ennuyeuses n'aiment généralement pas les variables vides. Edit: 1 octet enregistré grâce à @ CᴏɴᴏʀO'Bʀɪᴇɴ et 2 octets grâce à @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ (et un tas d'octets sur d'autres réponses aussi, bien que hélas non crédité).

Neil
la source
Je pense que vous pouvez supprimer un espace entre callet: x`, non?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Huh, donc vous pouvez. J'ai un tas de réponses qui doivent être mises à jour dans ce cas ...
Neil
2

Python 2, 265 260 254 octets

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)
acrolithe
la source
1

Python, 142 137 octets

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
la source
1

Bash, 41 octets

Ce script bash a pour effet secondaire de créer des répertoires s'ils n'existent pas, mais il devrait répondre aux exigences. Merci Karl et Neil pour vos améliorations.

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

Utilisation: bash getpath.sh "absolu" "nouveau"

Si vous n'aimez pas le stderr lorsque le deuxième argument est une chaîne vide, vous pouvez le tester comme suit (48 octets):

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

Tentative précédente de 30 octets (nécessite l'existence de répertoires): cd $ 1; [$ 2] && cd $ 2; echopwd

Bryn
la source
La question indique que les commandes devraient fonctionner, que les répertoires transmis existent ou non sur votre machine.
Dennis
Ah, je vois. Dommage.
Bryn
Bonjour et bienvenue chez PPCG! Normalement, si votre réponse ne fonctionne pas, vous la supprimez. Vous pouvez cliquer sur le lien de suppression au-dessus de ce commentaire.
NoOneIsHere
Vous pourriez mkdir -pvous assurer qu'ils existent.
Karl Napf
Merci, j'essaie une version avec mkdir. Je supprimerai cette réponse et j'en ajouterai une nouvelle si je la trouve.
Bryn
1

C #, 43 octets

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

1 octet enregistré grâce à @aloisdg

Path.Combinemet les arguments ensemble, et Path.GetFullPathrésout le ..\s

jlynch630
la source
Bonjour et bienvenue chez PPCG! Ce n'est pas un programme valide - incluez mainet une classe, ou changez-le en lanbda: a,b->...
NoOneIsHere
J'allais le poster :) Belle première soumission! vous pouvez supprimer l'espace après ,: (x, y)=>(x,y)
aloisdg dit Reinstate Monica
Les astuces C # pour le golf peuvent également vous intéresser.
aloisdg dit Réintégrer Monica
1

Node REPL, 8 12 octets

path.resolve

Heureusement, vous n'avez pas besoin de require()modules standard dans le REPL.

Suite de tests

https://repl.it/Cclo/1

(Si la sortie à la fin est true, elle correspond)

Patrick Roberts
la source
1

Javascript, 210 octets

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

Voici la suite de tests

Avec des sauts de ligne au lieu de points-virgules:

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
la source
0

Java 7, 83 octets

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

normalizeest nécessaire pour traiter les références relatives. addest utilisé pour gérer le deuxième chemin commençant par /, qui Paths.get(a, b)ne sera pas géré comme spécifié.

jaxad0127
la source
Bonjour et bienvenue chez PPCG! C'est un bon premier post!
NoOneIsHere
0

Bash, 38 octets

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

Ne nécessite pas de privilèges root et ne fait aucune supposition sur les fichiers, répertoires ou liens symboliques existants ou non.

Testez-le sur Ideone .

Comment ça fonctionne

[[ $2 = /* ]]teste si le deuxième argument de ligne de commande commence par /.

Si ce n'est pas le cas, le chemin est relatif et p=$1définit la variable p sur le premier argument de ligne de commande.

De cette façon $p/$2est le /$2cas $2est un chemin absolu et $1/$2si elle est un realtive.

Enfin, realpath -sm $p/$2imprime le chemin absolu canonique de $p/$2. Le -scommutateur fait que realpath ignore les liens symboliques et les -mcomposants manquants du commutateur.

Dennis
la source
0

Ruby, 16 octets

Puisqu'apparemment, l'utilisation d' une méthode de la bibliothèque standard est autorisée:

File.expand_path

Voir la suite au repl.it test .

Jordan
la source
La saisie via des variables n'est pas autorisée, mais la soumission de fonctions l'est, ce qui signifie que vous devez la raccourcir à File.expand_path:)
Nathan Merrill
Je recommanderais également de le tester par rapport à la suite de tests pour vous assurer qu'il fonctionne correctement sur tous les cas de test.
Nathan Merrill
@NathanMerrill Je l'ai fait, mais je vais continuer et coller quelque chose sur repl.it.
Jordan
Modifié pour inclure le lien de la suite de tests.
Jordan
0

GNU sed , 81 59 + 1 = 60 octets

+1 octet pour le -rdrapeau. Attend l'entrée sur STDIN sépare par un seul espace.

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

Essayez-le en ligne!

Explication

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
la source
0

Zsh , 15 octets

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

Le :amodificateur fait exactement cela.

Essayez-le en ligne!

GammaFunction
la source