Cálculo de directorio

19

Para este desafío, se le dará una ruta absoluta y una ruta "nueva" (que puede ser absoluta o relativa), y deberá devolver la ruta final.

Por ejemplo, si su directorio actual era /var/tmp/test:

my_diro my_dir/ debería volver/var/tmp/test/my_dir

../../my_dir debería volver /var/my_dir

/my_dir/./ debería volver /my_dir

../../../../../ debería volver /

Para ser más pedante:

  • Un directorio es una cadena no vacía que consiste en caracteres alfanuméricos y los símbolos -, _o.
  • Una ruta es una lista de 0 o más directorios , separados mediante /. Una ruta absoluta comienza con a /, una ruta relativa no. Los caminos pueden incluir un final /.

Necesita "resolver" la segunda ruta, dada la primera ruta.

El proceso de resolución es:

  1. Prueba si la segunda ruta es relativa. Si es así, inserte los directorios de la ruta absoluta al comienzo de la segunda ruta.
  2. Si alguno de los directorios lo es .., elimínelo junto con el directorio anterior. Si es el primer directorio, simplemente elimínelo.
  3. Si alguno de los directorios lo es ., elimínelo.
  4. Salida de la ruta absoluta final. No debe generar un final /.

No necesita manejar entradas incorrectas. Los comandos deberían funcionar, independientemente de si los directorios pasados ​​existen o no en su máquina. Puede suponer que todo es un directorio, incluso si tiene una extensión.

Casos de prueba

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

Este es un , ¡así que haga sus envíos lo más cortos posible en su idioma favorito!

Nathan Merrill
fuente
Algunas respuestas parecen suponer que los archivos (o enlaces simbólicos) con el mismo nombre que cualquier parte del árbol de directorios) no existen en la máquina. eso está permitido?
Dennis
¿Podemos tomar las dos entradas en el orden que deseemos?
Downgoat
Pregunta estúpida ... ¿puedo tener efectos secundarios? Específicamente, ¿efectos secundarios como, um, mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(o algo)?
gato
@dennis. La salida de los programas debe ser independiente del sistema de archivos
Nathan Merrill
@downgoat está bien
Nathan Merrill

Respuestas:

7

Retina , 44 bytes

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

^$
/

Se espera que la entrada sean las dos rutas separadas por un solo espacio.

Pruébalo en línea! (La primera línea habilita un conjunto de pruebas separado por salto de línea).

Martin Ender
fuente
3

Python, 53 bytes

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

Lote, 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

Molestamente, las expresiones por lotes generalmente no les gustan las variables vacías. Editar: guardado 1 byte gracias a @ CᴏɴᴏʀO'Bʀɪᴇɴ y 2 bytes gracias a @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ (y un montón de bytes en otras respuestas también, aunque desafortunadamente no acreditado).

Neil
fuente
Creo que puede eliminar un espacio entre cally: x`, ¿no?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Huh, para que puedas. Tengo un montón de respuestas que necesitan actualizarse en ese caso ...
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)
acrolito
fuente
1

Python, 142137 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
fuente
1

Bash, 41 bytes

Este script bash tiene el efecto secundario de crear directorios si no existen, pero debe cumplir con los requisitos. Gracias Karl y Neil por sus mejoras.

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

Uso: bash getpath.sh "absoluto" "nuevo"

Si no le gusta stderr cuando el segundo argumento es una cadena vacía, puede probarlo de la siguiente manera (48 bytes):

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

Intento anterior de 30 bytes (requiere que existan directorios): cd $ 1; [$ 2] && cd $ 2; echopwd

Bryn
fuente
La pregunta dice que los comandos deberían funcionar, independientemente de si los directorios pasados ​​existen o no en su máquina.
Dennis
Ah, ya veo. Demasiado.
Bryn
Hola y bienvenidos a PPCG! Normalmente, si su respuesta no funciona, la elimina. Puede hacer clic en el enlace Eliminar arriba de este comentario.
NoOneIsHere
Podrías mkdir -pasegurarte de que existan.
Karl Napf
Gracias, estoy probando una versión con mkdir. Eliminaré esta respuesta y agregaré una nueva si lo descubro.
Bryn
1

C #, 43 bytes

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

Guardado 1 byte gracias a @aloisdg

Path.Combinepone los argumentos juntos y Path.GetFullPathresuelve el ..\s

jlynch630
fuente
Hola y bienvenidos a PPCG! Este no es un programa válido, ya sea incluir mainy una clase, o cambiarlo a un idioma: a,b->...
NoOneIsHere
Iba a publicarlo :) ¡Buena presentación! puedes eliminar el espacio después de ,: (x, y)=>(x,y)
aloisdg dice Reinstate Monica
También los consejos de C # para el hilo de golf pueden interesarle.
aloisdg dice Reinstate Monica
1

Nodo REPL, 8 12 bytes

path.resolve

Afortunadamente, no es necesario tener require()módulos estándar en REPL.

Banco de pruebas

https://repl.it/Cclo/1

(Si la salida al final es true, coincide)

Patrick Roberts
fuente
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)}

Aquí está la suite de prueba

Con saltos de línea en lugar de punto y coma:

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
fuente
0

Java 7, 83 bytes

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

normalizees necesario para tratar referencias relativas. addse usa para manejar la segunda ruta que comienza con /, que Paths.get(a, b)no manejará como se especifica.

jaxad0127
fuente
Hola y bienvenidos a PPCG! Este es un buen primer post!
NoOneIsHere
0

Bash, 38 bytes

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

No requiere privilegios de root y no hace suposiciones sobre archivos, directorios o enlaces simbólicos existentes o no existentes.

Pruébalo en Ideone .

Cómo funciona

[[ $2 = /* ]]prueba si el segundo argumento de la línea de comandos comienza con /.

Si no es así, la ruta es relativa y p=$1establece la variable p en el primer argumento de línea de comandos.

De esta manera $p/$2es /$2si $2es un camino absoluto y $1/$2si es real.

Finalmente, realpath -sm $p/$2imprime el camino absoluto canónico de $p/$2. El -sconmutador hace que RealPath ignore los enlaces simbólicos, y al -mconmutador faltan componentes.

Dennis
fuente
0

Ruby, 16 bytes

Ya que aparentemente usa un método de la biblioteca estándar se permite :

File.expand_path

Ver el conjunto de pruebas en repl.it .

Jordán
fuente
La entrada a través de variables no está permitida, pero el envío de funciones sí lo es, lo que significa que debe acortarlo a File.expand_path:)
Nathan Merrill
También recomendaría probarlo contra el conjunto de pruebas para asegurarse de que funciona correctamente en todos los casos de prueba.
Nathan Merrill
@NathanMerrill lo hice, pero seguiré adelante y pegaré algo en repl.it.
Jordan
Editado para incluir el enlace del conjunto de pruebas.
Jordania
0

GNU sed , 81 59 + 1 = 60 bytes

+1 byte para -rbandera. Espera entrada en STDIN separa por un solo espacio.

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

Pruébalo en línea!

Explicación

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
Jordán
fuente