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!


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


3

Python, 53 bytes

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

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


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)

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

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


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


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



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

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.


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.


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 .


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.