Perhitungan direktori


19

Untuk tantangan ini, Anda akan diberikan jalur absolut, dan jalur "baru" (yang bisa absolut atau relatif), dan Anda harus mengembalikan jalur terakhir.

Misalnya, jika direktori Anda saat ini adalah /var/tmp/test:

my_diratau my_dir/ harus kembali/var/tmp/test/my_dir

../../my_dir harus kembali /var/my_dir

/my_dir/./ harus kembali /my_dir

../../../../../ harus kembali /

Untuk menjadi lebih bertele-tele:

  • Sebuah direktori adalah string non-kosong yang terdiri dari karakter alfanumerik dan simbol-simbol -, _atau.
  • Path adalah daftar 0 atau lebih direktori , dipisahkan menggunakan /. Jalur absolut dimulai dengan a /, jalur relatif tidak. Jalur dapat menyertakan akhiran /.

Anda perlu "menyelesaikan" jalur kedua, mengingat jalur pertama.

Proses penyelesaiannya adalah:

  1. Uji apakah jalur kedua relatif. Jika demikian, maka masukkan direktori jalur absolut ke awal jalur kedua.
  2. Jika ada salah satu direktori .., maka hapus dan direktori sebelumnya. Jika ini adalah direktori pertama, cukup hapus saja.
  3. Jika ada direktori ., maka hapus.
  4. Keluarkan jalan absolut terakhir. Anda seharusnya tidak menghasilkan akhir /.

Anda tidak perlu menangani input yang salah. Perintah harus bekerja, apakah direktori yang dilewati benar-benar ada di mesin Anda. Anda dapat mengasumsikan bahwa semuanya adalah direktori, bahkan jika ia memiliki ekstensi.

Uji kasus

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

Ini adalah , jadi buat kiriman Anda sesingkat mungkin dalam bahasa favorit Anda!


Beberapa jawaban tampaknya menganggap bahwa file (atau symlink) dengan nama yang sama dengan bagian mana pun dari pohon direktori) tidak ada pada mesin. Apakah itu diizinkan?
Dennis

Bisakah kita mengambil dua input dalam urutan yang kita inginkan?
Downgoat

Pertanyaan bodoh ... bisakah saya memiliki efek samping? Secara khusus, efek samping seperti, um, mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(atau sesuatu)?
kucing

@dennis. Output dari program-program tersebut harus independen dari sistem file
Nathan Merrill

@ downgoat tidak masalah
Nathan Merrill

Jawaban:


7

Retina , 44 byte

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

^$
/

Input diharapkan menjadi dua jalur yang dipisahkan oleh ruang tunggal.

Cobalah online! (Baris pertama memungkinkan suite tes yang dipisahkan dengan linefeed.)


3

Python, 53 byte

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

3

Batch, 282 281 279 276 byte

@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

Ekspresi Annoyingly Batch umumnya tidak suka variabel kosong. Sunting: Disimpan 1 byte berkat @ CᴏɴᴏʀO'Bʀɪᴇɴ dan 2 byte terima kasih ke @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ (dan banyak byte pada jawaban lain juga, meskipun sayangnya tidak terakreditasi).


Saya pikir Anda dapat menghapus spasi di antara calldan: x`, tidak?
Conor O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Huh, jadi kamu bisa. Saya punya banyak jawaban yang perlu diperbarui dalam kasus itu ...
Neil

2

Python 2, 265 260 254 byte

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 byte

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 byte

Skrip bash ini memiliki efek samping membuat direktori jika tidak ada, tetapi harus memenuhi persyaratan. Terima kasih Karl dan Neil untuk perbaikan Anda.

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

Penggunaan: bash getpath.sh "absolute" "baru"

Jika Anda tidak menyukai stderr ketika argumen kedua adalah string kosong, Anda dapat mengujinya sebagai berikut (48 byte):

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

Upaya 30 byte sebelumnya (membutuhkan direktori ada): cd $ 1; [$ 2] && cd $ 2; echopwd


Pertanyaannya mengatakan Perintah harus bekerja, apakah direktori yang dilewati benar-benar ada di mesin Anda.
Dennis

Ah, begitu. Sangat buruk.
Bryn

Halo, dan selamat datang di PPCG! Biasanya, jika jawaban Anda tidak berhasil, Anda menghapusnya. Anda dapat mengklik tautan hapus di atas komentar ini.
NoOneIsHere

Anda bisa mkdir -pmemastikan mereka ada.
Karl Napf

Terima kasih, saya mencoba versi dengan mkdir. Saya akan menghapus jawaban ini dan menambahkan yang baru jika saya mengetahuinya.
Bryn

1

C #, 43 byte

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

Disimpan 1 byte berkat @aloisdg

Path.Combinemenempatkan argumen bersama, dan Path.GetFullPathmenyelesaikan ..\s


Halo, dan selamat datang di PPCG! Ini bukan program yang valid - baik termasuk maindan kelas, atau mengubahnya menjadi lanbda: a,b->...
NoOneIsHere

Saya akan mempostingnya :) Kiriman pertama yang bagus! Anda dapat menghapus spasi setelah ,: (x, y)=>(x,y)
aloisdg mengatakan Reinstate Monica



1

Javascript, 210 byte

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

Berikut ini adalah test suite

Dengan linebreak alih-alih titik koma:

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 byte

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

normalizediperlukan untuk berurusan dengan referensi relatif. adddigunakan untuk menangani jalur kedua dimulai dengan /, yang Paths.get(a, b)tidak akan menangani seperti yang ditentukan.


Halo, dan selamat datang di PPCG! Ini adalah posting pertama yang bagus!
NoOneIsHere

0

Bash, 38 byte

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

Tidak memerlukan hak akses root dan tidak membuat asumsi tentang file, direktori atau tautan simbolik yang ada atau tidak ada.

Uji di Ideone .

Bagaimana itu bekerja

[[ $2 = /* ]]menguji apakah argumen baris perintah kedua dimulai dengan /.

Jika tidak, jalur relatif dan p=$1menetapkan variabel p ke argumen baris perintah pertama.

Cara ini $p/$2adalah /$2jika $2jalur absolut dan $1/$2jika jalan realtive.

Akhirnya, realpath -sm $p/$2mencetak jalur absolut kanonik $p/$2. The -sberalih merek realpath mengabaikan link simbolik, dan -mberalih hilang komponen.


0

Ruby, 16 byte

Karena tampaknya menggunakan metode dari perpustakaan standar diperbolehkan:

File.expand_path

Lihat test suite di repl.it .


Input melalui variabel tidak diizinkan, tetapi pengiriman fungsi, adalah, yang berarti Anda harus mempersingkatnya menjadi File.expand_path:)
Nathan Merrill

Saya juga merekomendasikan untuk benar-benar mengujinya terhadap test suite untuk memastikan bahwa itu berfungsi dengan benar pada semua test case.
Nathan Merrill

@NathanMerrill yang saya lakukan, tapi saya akan pergi ke depan dan menempelkan sesuatu pada repl.it.
Jordan

Diedit untuk menyertakan tautan test suite.
Jordan

0

GNU sed , 81 59 + 1 = 60 byte

+1 byte untuk -rbendera. Mengharapkan input pada STDIN terpisah oleh satu ruang.

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

Cobalah online!

Penjelasan

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.