絶対パスを短くする


17

現在の作業ディレクトリを参照として使用して、Linuxツールへのコマンドラインパラメーターなどの長い絶対パスを短縮できる場合があります。

$ pwd
/home/heh

$ cat /home/heh/mydir/myfile
my stuff

$ cat mydir/myfile
my stuff

この課題では、2つのパラメーターを受け取る関数またはプログラムを作成する必要があります。

  1. Linux形式を使用した絶対パス(で始まる/
  2. 同じ形式を使用した現在のディレクトリ

出力は、次のうち短い方です。

  • 入力1は変更なし
  • 絶対パスと同じファイル/ディレクトリを参照する相対パス

細かい点:

  • オペレーティングシステムがLinuxと互換性がある場合は、入力として受け取る代わりに、システムの現在のディレクトリを使用できます。
  • 入力には英数字(およびパス区切り文字)のみが含まれると想定できます。
  • 入力絶対パス/の最後にパス区切り記号がないと仮定できます
  • 入力現在のディレクトリ/の最後にパス区切り文字があると仮定できます
  • 絶対パスが既存のファイルを参照している、またはその一部がアクセス可能なディレクトリであると想定することはできません。ただし、現在のディレクトリは有効であると想定できます。
  • いずれかのパスの近くにシンボリックリンクがないと仮定できます-シンボリックリンクを処理する特別な方法を必要としないため
  • 入力のいずれかがルートディレクトリである場合をサポートする必要はありません
  • 「現在のディレクトリ」として出力する必要があります.(空の文字列は無効です)

テストケース(input1、input2、output):

/home/user/mydir/myfile
/home/user
mydir/myfile

/var/users/admin/secret/passwd
/var/users/joe/hack
../../admin/secret/passwd

/home/user/myfile
/tmp/someplace
/home/user/myfile

/dir1/dir2
/dir1/dir2/dir3/dir4
../..

/dir1/dir2
/dir1/dir2
.

1
「入力の現在のディレクトリ/の最後にパス区切り文字があると仮定できます」。ただし、例ではそうではありません。
シャギー

1
私はこの方法が好きですが、別の方法が好きな人もいます
アナトリグ


絶対パスと相対パスの長さが同じ場合はどうなりますか?
デニス

1
これは、いくつかの重要なテストケースが欠落しています。 /home/test /home/user/mydir/myfile /home/test/a/b /a/b/d/e /a/b
ネイサンメリル

回答:


7

ジュリア0.5、32バイト

!,~=relpath,endof
t->~t<~!t?t:!t

これは現在の作業ディレクトリをベースとして使用し、現時点ではTIOでテストできません。

実行例

警告:これにより、ファイルシステムが変更されます。

$ sudo julia --quiet
julia> function test(target,base)
       mkpath(base)
       cd(base)
       shorten(target)
       end
test (generic function with 1 method)
julia> !,~=relpath,endof
(relpath,endof)

julia> shorten = t->~t<~!t?t:!t
(::#1) (generic function with 1 method)

julia> test("/home/user/mydir/myfile","/home/user")
"mydir/myfile"

julia> test("/var/users/admin/secret/passwd","/var/users/joe/hack")
"../../admin/secret/passwd"

julia> test("/home/user/myfile","/tmp/someplace")
"/home/user/myfile"

julia> test("/dir1/dir2","/dir1/dir2/dir3/dir4")
"../.."

julia> test("/dir1/dir2","/dir1/dir2")
"."

代替バージョン、35バイト(二項)

^,~=relpath,endof
t-b=~t<~t^b?t:t^b

これは、入力としてベースディレクトリを取るため、ファイルシステムを変更せずにテストできます。

オンラインでお試しください!


Base.-明示的にインポートしない限り、エラーを再定義しますか?
ジュリアン・ウルフ

0.5では、エラーが発生する可能性がありますが、-再定義する前に使用する場合のみです。0.4では、再定義の前に使用するかどうかにかかわらず、警告を出力します。
デニス

9

JavaScript(ES6)、 107 106バイト

カリー化構文の絶対パスaと現在のパスを使用cします(a)(c)

a=>c=>(A=a.split`/`,s='',c.split`/`.map(d=>!s&A[0]==d?A.shift():s+='../'),s+=A.join`/`)[a.length]?a:s||'.'

テストケース


と非常に素晴らしいトリック[a.length]!Node.jsの回答を改善するために借りることができますか?
ツェッペリン

@zeppelin確かに。頑張れ!
アーナルド


5

ES6(Node.js REPL)、 565446、45バイト

  • 「。」の代わりに空の文字列を使用します 現在のディレクトリ(入力時)を示すため、-1バイト
  • [f.length]@Arnauldの答えからトリックを借りました、-6バイト
  • 明示的なディレクトリパラメータ-2バイトの代わりに現在のディレクトリを使用します
  • 余分な括弧を削除、-2バイト

ゴルフ

f=>(r=path.relative("",f))[f.length]?f:r||"."

テスト

> F=f=>(r=path.relative("",f))[f.length]?f:r||"."
[Function: F]

> F("/home/user/mydir/myfile")
'mydir/myfile'

> F("/var/users/admin/secret/passwd")
'../../admin/secret/passwd'

> F("/home/user/myfile")
'/home/user/myfile'

> F("/dir1/dir2")
'../..'

> F("/dir1/dir2")
'.'

node.js関数を許可しませんか?
ダウンゴート

@Downgoat Javascriptラムダは、回答の形式として広く受け入れられているため、Node.jsを別の方法で処理する必要がある理由はわかりません。
ツェッペリン

4

Python 2、135 144バイト

i=0
a,c=input()
b,d=a.split('/')*(a!=c),c.split('/')
while b[:i+1]==d[:i+1]:i+=1
print'.'[i:]or min('/'.join(['..']*len(d[i:])+b[i:]),a,key=len)

オンラインでお試しください!

ちょっと長いですが、組み込みのパス関数なしで解決したかったのです。

編集: Nathan Merrillが提供するテストケースのアカウントに9バイトを追加



2

Python 3 – 53バイト

を使用してos.path

import os
lambda x:min(x,os.path.relpath(x),key=len)

完全なプログラム(61バイト):

import os
x=input();print(min(x,os.path.relpath(x),key=len))

うーん、良い点。Pythonが今、先頭に立っています。
matsjoyce

@anatolygハ、私は少なくとも1つのテストケースを見逃すことを知っていました...😒すべて修正されました。
matsjoyce

1

PHP、204バイト

[,$l,$p]=$argv;$z=($d=array_diff_assoc)($y=($w=explode)("/",$p),$x=$w("/",$l));$m=str_pad("",3*count($z)-1,"../");$j=join("/",$r=$d($x,$y));echo$l!=$p?strlen($u=$m&&$j?"$m/$j":$m.$j)<strlen($l)?$u:$l:".";

テストケース

拡大

[,$l,$p]=$argv;
$z=($d=array_diff_assoc)($y=($w=explode)("/",$p),$x=$w("/",$l));
$m=str_pad("",3*count($z)-1,"../");
$j=join("/",$r=$d($x,$y));
echo$l!=$p
    ?strlen($u=$m&&$j?"$m/$j":$m.$j)<strlen($l)
      ?$u
      :$l
    :".";

../../代わりに出力of ../..が許可される場合、175バイトに短縮できます。

[,$l,$p]=$argv;$z=($d=array_diff_assoc)($y=($w=explode)("/",$p),$x=$w("/",$l));echo$l!=$p?strlen($m=str_pad("",3*count($z),"../").join("/",$r=$d($x,$y)))<strlen($l)?$m:$l:".";

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.