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!


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


3

Python, 53 octets

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

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é).


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)

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

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


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


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)


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

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é.


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.


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 .


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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.