디렉토리 계산


19

이 문제를 해결하려면 절대 경로와 "새"경로 (절대 또는 상대 경로)가 제공되며 최종 경로를 반환해야합니다.

예를 들어, 현재 디렉토리가 /var/tmp/test다음과 같은 경우

my_dir또는 my_dir/ 돌아와야한다/var/tmp/test/my_dir

../../my_dir 돌아와야한다 /var/my_dir

/my_dir/./ 돌아와야한다 /my_dir

../../../../../ 돌아와야한다 /

더 pedantic하려면 :

  • 디렉토리는 알파벳 문자로 구성된 비어 있지 않은 문자열과 기호 -, _또는.
  • 경로 는를 사용하여 분리 된 0 개 이상의 디렉토리 목록입니다/ . 절대 경로는로 시작 /하고 상대 경로는 시작 하지 않습니다. 경로는 결말을 포함 할 수 있습니다 /.

첫 번째 경로가 주어지면 두 번째 경로를 "해결"해야합니다.

해결 과정은 다음과 같습니다.

  1. 두 번째 경로가 상대적인지 테스트하십시오. 그렇다면 절대 경로의 디렉토리를 두 ​​번째 경로의 시작 부분에 삽입하십시오.
  2. 디렉토리가 있으면 디렉토리 ..와 이전 디렉토리를 제거하십시오. 첫 번째 디렉토리 인 경우 간단히 제거하십시오.
  3. 디렉토리가 있으면 .제거하십시오.
  4. 최종 절대 경로를 출력합니다. 결말을 출력해서는 안됩니다 /.

잘못된 입력을 처리 할 필요가 없습니다. 전달 된 디렉토리가 시스템에 실제로 존재하는지 여부에 관계없이 명령이 작동해야합니다. 확장자가 있더라도 모든 것이 디렉토리라고 가정 할 수 있습니다.

테스트 사례

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

이것은 이므로 원하는 언어로 가능한 한 짧게 제출하십시오!


일부 답변 은 디렉토리 트리의 일부와 동일한 이름을 가진 파일 (또는 심볼릭 링크) 이 컴퓨터에 존재 하지 않는다고 가정 한 것 같습니다. 허용 되나요?
Dennis

원하는 순서대로 두 입력을 취할 수 있습니까?
Downgoat

바보 같은 질문 ... 부작용이 있습니까? 구체적으로, 음, mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(또는 무엇인가) 부작용 ?
고양이

@ 데니스. 프로그램의 출력은 파일 시스템과 독립적이어야합니다
Nathan Merrill

@ downgoat 괜찮습니다
Nathan Merrill

답변:



3

파이썬, 53 바이트

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

3

배치, 282 281 279 276 바이트

@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

성가신 배치 식은 일반적으로 빈 변수를 좋아하지 않습니다. 편집 : @ CᴏɴᴏʀO'Bʀɪᴇɴ 덕분에 1 바이트를 저장하고 @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ 덕분에 2 바이트를 절약했습니다 (아아도 크레딧은 없지만 다른 답변의 바이트도 많이 있습니다).


call와 : x` 사이의 공백을 제거 할 수 있다고 생각합니다 .
코너 O'Brien

@ CᴏɴᴏʀO'Bʀɪᴇɴ Huh, 가능합니다. 이 경우에 업데이트가 필요한 답변이 많이 있습니다 ...
Neil

2

파이썬 2, 265 260 254 바이트

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

파이썬 142 137 바이트

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

배쉬, 41 바이트

이 bash 스크립트는 디렉토리가 존재하지 않으면 디렉토리를 작성하는 부작용이 있지만 요구 사항을 충족해야합니다. 개선을 위해 KarlNeil 에게 감사드립니다 .

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

사용법 : bash getpath.sh "absolute" "new"

두 번째 인수가 빈 문자열 일 때 stderr가 마음에 들지 않으면 다음과 같이 테스트 할 수 있습니다 (48 바이트).

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

이전 30 바이트 시도 (디렉토리가 있어야 함) : cd $ 1; [$ 2] && cd $ 2; echopwd


질문은 전달 된 디렉토리가 실제로 컴퓨터에 존재하는지 여부에 관계없이 명령이 작동해야한다는 것입니다.
Dennis

아, 알겠습니다 너무 나쁘다.
Bryn

안녕하세요, PPCG에 오신 것을 환영합니다! 일반적으로 답변이 작동하지 않으면 삭제합니다. 이 댓글 위의 삭제 링크를 클릭 할 수 있습니다.
NoOneIsHere7

당신은 할 수 mkdir -p그들이 존재 확인합니다.
Karl Napf

고마워, 나는 mkdir로 버전을 시도하고있다. 이 답변을 삭제하고 알아 내면 새 답변을 추가하겠습니다.
Bryn

1

C #, 43 바이트

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

@aloisdg 덕분에 1 바이트 절약

Path.Combine인수를 모아서 s를 Path.GetFullPath해결합니다...\


안녕하세요, PPCG에 오신 것을 환영합니다! 이것은 유효한 프로그램이 아닙니다-포함 main과 클래스 또는 란다로 변경하십시오 : a,b->...
NoOneIsHere

나는 그것을 게시하려고했다 :) 멋진 첫 번째 제출! 다음과 같이 공백을 제거 할 수 있습니다 ,: (x, y)=>(x,y)
aloisdg는 Reinstate Monica

또한 골프 스레드에 대한 C # 팁 이 관심을 가질 수 있습니다.
aloisdg는 Reinstate Monica


1

자바 스크립트, 210 바이트

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

테스트 스위트입니다

세미콜론 대신 줄 바꿈 사용 :

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

자바 7, 83 바이트

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

normalize상대 참조를 처리하는 데 필요합니다. add시작하여 제 2 경로 처리하는 데 사용 /되는 Paths.get(a, b)지정된대로 처리 할 것이다.


안녕하세요, PPCG에 오신 것을 환영합니다! 이것은 좋은 첫 번째 게시물입니다!
NoOneIsHere7

0

배쉬, 38 바이트

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

루트 권한이 필요하지 않으며 기존 또는 존재하지 않는 파일, 디렉토리 또는 기호 링크에 대한 가정을하지 않습니다.

Ideone에서 테스트하십시오 .

작동 원리

[[ $2 = /* ]]두 번째 명령 줄 인수가로 시작하는지 테스트합니다 /.

그렇지 않은 경우 경로는 상대적이며 p=$1변수 p 를 첫 번째 명령 줄 인수로 설정합니다.

이 방법 $p/$2/$2if $2가 절대 경로이고 $1/$2실제 경로 인 경우입니다.

마지막으로 realpath -sm $p/$2표준의 절대 경로를 인쇄합니다 $p/$2. -s스위치 차종 realpath 심볼릭 링크를 무시하고 -m스위치 누락 된 구성 요소.


0

루비, 16 바이트

표준 라이브러리의 메소드를 사용 하는 것이 허용 되므로 :

File.expand_path

repl.it테스트 스위트를 참조하십시오 .


변수를 통한 입력은 허용되지 않지만, 기능 제출, 당신이 그것을 단축해야하는 수단입니다 File.expand_path:)
나단 메릴

또한 실제로 모든 테스트 사례에서 올바르게 작동하는지 테스트 스위트에 대해 테스트하는 것이 좋습니다.
Nathan Merrill

@NathanMerrill 내가했지만 repl.it에 뭔가를 붙일 것입니다.
Jordan

테스트 스위트 링크를 포함하도록 편집되었습니다.
Jordan

0

GNU sed , 81 59 + 1 = 60 바이트

-r플래그의 경우 +1 바이트 STDIN의 입력은 단일 공백으로 구분됩니다.

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

온라인으로 사용해보십시오!

설명

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.