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!

Nathan Merrill
sumber
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.)

Martin Ender
sumber
3

Python, 53 byte

from os.path import*;p=lambda a,n:normpath(join(a,n))
orlp
sumber
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).

Neil
sumber
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)
akrolit
sumber
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])
orlp
sumber
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

Bryn
sumber
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

jlynch630
sumber
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
Juga C # Tips untuk benang golf mungkin menarik bagi Anda.
aloisdg berkata Reinstate Monica
1

Node REPL, 8 12 byte

path.resolve

Untungnya Anda tidak harus memiliki require()modul standar dalam REPL.

Test Suite

https://repl.it/Cclo/1

(Jika output pada akhirnya true, itu cocok)

Patrick Roberts
sumber
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)
}
CShark
sumber
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.

jaxad0127
sumber
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.

Dennis
sumber
0

Ruby, 16 byte

Karena tampaknya menggunakan metode dari perpustakaan standar diperbolehkan:

File.expand_path

Lihat test suite di repl.it .

Yordania
sumber
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
Yordania
sumber
0

Zsh , 15 byte

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

The :apengubah tidak tepat ini.

Cobalah online!

Fungsi Gamma
sumber