ディレクトリ計算


19

このチャレンジでは、絶対パスと「新しい」パス(絶対パスまたは相対パス)が与えられ、最終パスを返す必要があります。

たとえば、現在のディレクトリが/var/tmp/test次の場合:

my_dirまたはmy_dir/ 戻る必要があります/var/tmp/test/my_dir

../../my_dir 帰るべき /var/my_dir

/my_dir/./ 帰るべき /my_dir

../../../../../ 帰るべき /

もっと用心深くなるには:

  • ディレクトリには、英数字と記号からなる非空の文字列である-_または.
  • パスは、を使用して区切られた0個以上のディレクトリのリストです/。絶対パスはで始まり/、相対パスはそうではありません。パスには終了を含めることができます/

最初のパスを指定して、2番目のパスを「解決」する必要があります。

解決のプロセスは次のとおりです。

  1. 2番目のパスが相対パスかどうかをテストします。その場合、絶対パスのディレクトリを2番目のパスの先頭に挿入します。
  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"
"/."          ""        -> "/"

これはですので、お気に入りの言語で投稿をできるだけ短くしてください!


一部の答えは、ディレクトリツリーの任意の部分と同じ名前のファイル(またはシンボリックリンク)がマシン上に存在しないと仮定しているように見えます。それは許されますか?
デニス

2つの入力を任意の順序で取得できますか?
ダウンゴート

愚かな質問...副作用がありますか?具体的には、うーん、mkdir $patha; cd $patha; mkdir $pathb; cd $pathb; echo `abspath`(または何か)のような副作用?

@dennis。プログラムの出力は、ファイルシステムに依存しない必要があります
ネイサンメリル

@downgoatそれはいいです
ネイサンメリル

回答:



3

Python、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`の間のスペースを削除できると思いますか?
コナーオブライエン

@CᴏɴᴏʀO'Bʀɪᴇɴええ、そうすることができます。私は...その場合の必要性更新という答えの束を持っている
ニール・

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

Python、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

Bash、41バイト

このbashスクリプトには、ディレクトリが存在しない場合にディレクトリを作成するという副作用がありますが、要件を満たす必要があります。改善してくれたカールニールに感謝します。

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

使用法:bash getpath.sh "absolute" "new"

2番目の引数が空の文字列である場合にstderrが気に入らない場合は、次のようにテストできます(48バイト)。

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

以前の30バイトの試行(ディレクトリが存在する必要があります): cd $ 1; [$ 2] && cd $ 2; echopwd


質問は、渡されたディレクトリが実際にマシン上に存在するかどうかに関係なく、コマンドは動作するはずだ
デニス

ああ、なるほど。残念な。
ブリン

こんにちは、PPCGへようこそ!通常、回答が機能しない場合は、削除します。このコメントの上にある削除リンクをクリックできます。
NoOneIsHere

mkdir -pそれらが存在することを確認できます。
カールナップ

おかげで、mkdirを使用したバージョンを試しています。この答えを削除し、それがわかったら新しいものを追加します。
ブリン

1

C#、43バイト

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

@aloisdgのおかげで1バイト節約

Path.Combine引数をまとめて、s をPath.GetFullPath解決します..\


こんにちは、PPCGへようこそ!これは有効なプログラムではありません。インクルードmainとクラス、またはそれをlanbdaに変更します:a,b->...
NoOneIsHere

私はそれを投稿するつもりだった:)素敵な最初の提出!あなたは後にスペースを削除することができます,(x, y)=>(x,y)
aloisdg言う復活モニカ



1

Javascript、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

Java 7、83バイト

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

normalize相対参照を扱うために必要です。add始まる第二のパス処理するために使用される/Paths.get(a, b)指定されたとおり処理しないであろうが。


こんにちは、PPCGへようこそ!これは良い最初の投稿です!
NoOneIsHere

0

Bash、38バイト

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

ルート権限を必要とせず、既存または存在しないファイル、ディレクトリ、またはシンボリックリンクに関する仮定を行いません。

Ideoneでテストします。

使い方

[[ $2 = /* ]]2番目のコマンドライン引数がで始まるかどうかをテストし/ます。

そうでない場合、パスは相対パスであり、p=$1変数pを最初のコマンドライン引数に設定します。

この方法$p/$2/$2、if $2が絶対パスであり$1/$2、それが現実的なパスである場合です。

最後に、realpath -sm $p/$2の正規の絶対パスを出力し$p/$2ます。-sスイッチは、作るのrealpathシンボリックリンクを無視し、-mスイッチはコンポーネントが不足します。


0

Ruby、16バイト

どうやら標準ライブラリのメソッドを使用することが許可されているため:

File.expand_path

repl.itテストスイートを参照してください。


変数を介して入力許可されていないが、関数の提出、され、どのあなたがするそれを短くする必要があることを意味File.expand_path:)
ネイサンメリル

また、テストスイートに対して実際にテストして、すべてのテストケースで正しく動作することを確認することもお勧めします。
ネイサンメリル

@NathanMerrillでしたが、repl.itに何かを追加します。
ヨルダン

テストスイートリンクを含めるように編集されました。
ヨルダン

0

GNU sed81 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.