Find common directory path: Difference between revisions

no edit summary
(→‎{{header|Python}}: os.path.commonpath for Pythons 3.5+)
No edit summary
(27 intermediate revisions by 16 users not shown)
Line 17:
{{trans|C}}
 
<langsyntaxhighlight lang="11l">F find_common_directory_path(paths, sep = ‘/’)
V pos = 0
L
Line 34:
‘/home/user1/tmp/coverage/test’,
‘/home/user1/tmp/covert/operator’,
‘/home/user1/tmp/coven/members’]))</langsyntaxhighlight>
 
{{out}}
Line 42:
 
=={{header|Ada}}==
<langsyntaxhighlight lang="ada">
with Ada.Text_IO; use Ada.Text_IO;
 
Line 80:
);
end Test_Common_Path;
</syntaxhighlight>
</lang>
Output:
<pre>
Line 87:
 
=={{header|Aime}}==
<langsyntaxhighlight lang="aime">cdp(...)
{
integer e;
Line 111:
 
0;
}</langsyntaxhighlight>
 
=={{header|ALGOL 68}}==
Line 120:
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d]}}
 
<langsyntaxhighlight lang="algol68"># Utilities code #
 
CHAR dir sep = "/"; # Assume POSIX #
Line 177:
);
print((dir name(common prefix(dir list)), new line))
)</langsyntaxhighlight>
Output:
<pre>
/home/user1/tmp
</pre>
 
=={{header|AppleScript}}==
<syntaxhighlight lang="applescript">on commonDirectoryPath(thePaths, separator)
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to separator
set path1 to thePaths's beginning
set path1Components to path1's text items
set maxC to (count path1Components)
repeat with nextPath in (thePaths's rest)
if (maxC = 0) then exit repeat
set theseComponents to nextPath's text items
set componentCount to (count theseComponents)
if (componentCount < maxC) then set maxC to componentCount
repeat with c from 1 to maxC
if (theseComponents's item c ≠ path1Components's item c) then
set maxC to c - 1
exit repeat
end if
end repeat
end repeat
if (maxC > 0) then
set commonPath to path1's text 1 thru text item maxC
else
set commonPath to ""
end if
set AppleScript's text item delimiters to astid
return commonPath
end commonDirectoryPath
 
return commonDirectoryPath({"/home/user1/tmp/coverage/test", ¬
"/home/user1/tmp/covert/operator", ¬
"/home/user1/tmp/coven/members"}, "/")</syntaxhighlight>
 
{{output}}
<syntaxhighlight lang="applescript">"/home/user1/tmp"</syntaxhighlight>
 
=={{header|Arturo}}==
 
<syntaxhighlight lang="rebol">commonPathPrefix: function [lst][
paths: map lst => [split.by:"/" &]
 
common: new []
firstPath: first paths
loop .with:'i firstPath 'part [
found: true
loop paths 'p [
if part <> get p i [
found: false
break
]
]
if found -> 'common ++ part
]
return join.with:"/" common
]
 
print commonPathPrefix [
"/home/user1/tmp/coverage/test"
"/home/user1/tmp/covert/operator"
"/home/user1/tmp/coven/members"
]</syntaxhighlight>
 
{{out}}
 
<pre>/home/user1/tmp</pre>
 
=={{header|AutoHotkey}}==
<langsyntaxhighlight lang="autohotkey">Dir1 := "/home/user1/tmp/coverage/test"
Dir2 := "/home/user1/tmp/covert/operator"
Dir3 := "/home/user1/tmp/coven/members"
Line 198 ⟶ 264:
Else Break
 
MsgBox, % Result</langsyntaxhighlight>
Message box shows:
<pre>/home/user1/tmp</pre>
 
=={{header|AWK}}==
<langsyntaxhighlight lang="awk"># Finds the longest common directory of paths[1], paths[2], ...,
# paths[count], where sep is a single-character directory separator.
function common_dir(paths, count, sep, b, c, f, i, j, p) {
Line 243 ⟶ 309:
a[3] = "/home/user1/tmp/coven/members"
print common_dir(a, 3, "/")
}</langsyntaxhighlight>
 
Prints <tt>/home/user1/tmp</tt>.
Line 255 ⟶ 321:
Also, under FreeBASIC, the <code>pathSep</code> arg to <code>commonPath$</code> could be made optional, or even system-dependent.
 
<langsyntaxhighlight lang="qbasic">DECLARE FUNCTION commonPath$ (paths() AS STRING, pathSep AS STRING)
 
DATA "/home/user2", "/home/user1/tmp/covert/operator", "/home/user1/tmp/coven/members"
Line 306 ⟶ 372:
commonPath$ = tmpstr1
END IF
END FUNCTION</langsyntaxhighlight>
 
=={{header|BASIC256}}==
{{trans|GW-BASIC}}
<syntaxhighlight lang="basic256">x = "/home/user1/tmp/coverage/test"
y = "/home/user1/tmp/covert/operator"
z = "/home/user1/tmp/coven/members"
 
a = length(x)
if a > length(y) then a = length(y)
if a > length(z) then a = length(z)
for i = 1 to a
if mid(x, i, 1) <> mid(y, i, 1) then exit for
next i
a = i - 1
 
for i = 1 to a
if mid(x, i, 1) <> mid(z, i, 1) then exit for
next i
a = i - 1
 
if mid(x, i, 1) <> "/" then
for i = a to 1 step -1
if "/" = mid(x, i, 1) then exit for
next i
end if
 
REM Task description says no trailing slash, so...
a = i - 1
print "Common path is '"; left(x, a); "'"</syntaxhighlight>
 
=={{header|Batch File}}==
<langsyntaxhighlight lang="dos">
@echo off
setlocal enabledelayedexpansion
Line 371 ⟶ 466:
endlocal
exit /b
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 378 ⟶ 473:
 
=={{header|BBC BASIC}}==
<langsyntaxhighlight lang="bbcbasic"> DIM path$(3)
path$(1) = "/home/user1/tmp/coverage/test"
Line 396 ⟶ 491:
NEXT J%
UNTIL I% = 0
= LEFT$(p$(1), O%-1)</langsyntaxhighlight>
 
=={{header|C}}==
<langsyntaxhighlight Clang="c">#include <stdio.h>
 
int common_len(const char *const *names, int n, char sep)
Line 432 ⟶ 527:
 
return 0;
}</langsyntaxhighlight>output:<syntaxhighlight lang="text">Common path: /home/user1/tmp</langsyntaxhighlight>
 
=={{header|C sharp|C#}}==
 
<langsyntaxhighlight lang="csharp">
using System;
using System.Collections.Generic;
Line 500 ⟶ 595:
}
 
</syntaxhighlight>
</lang>
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <algorithm>
#include <iostream>
#include <string>
Line 533 ⟶ 628:
std::string::size_type found = compareString.rfind( separator , maxCharactersCommon ) ;
return compareString.substr( 0 , found ) ;
}</langsyntaxhighlight>
Output:
<pre>
Line 540 ⟶ 635:
 
=={{header|Clojure}}==
<langsyntaxhighlight lang="clojure">(use '[clojure.string :only [join,split]])
 
(defn common-prefix [sep paths]
Line 553 ⟶ 648:
["/home/user1/tmp/coverage/test"
"/home/user1/tmp/covert/operator"
"/home/user1/tmp/coven/members"]))</langsyntaxhighlight>
 
 
=={{header|Common Lisp}}==
The strings represent file paths, so instead of treating them as simple strings, this uses the specialized pathname functions, which are more robust and generic.
<syntaxhighlight lang="lisp">
(defun common-directory-path (&rest paths)
(do* ((pathnames (mapcar #'(lambda (path) (cdr (pathname-directory (pathname path)))) paths)) ; convert strings to lists of subdirectories
(rem pathnames (cdr rem))
(pos (length (first rem))) ) ; position of first mismatched element
((null (cdr rem)) (make-pathname :directory (cons :absolute (subseq (first pathnames) 0 pos)))) ; take the common sublists and convert back to a pathname
(setq pos (min pos (mismatch (first rem) (second rem) :test #'string-equal))) )) ; compare two paths
</syntaxhighlight>
 
 
{{out}}
<pre>(common-directory-path "/home/user1/tmp/coverage/test" "/home/user1/tmp/covert/operator" "/home/user1/tmp/coven/members")
==> #P"/home/user1/tmp/"</pre>
 
=={{header|D}}==
This code uses the std.algorithm.commonPrefix function that finds the common prefix of two ranges.
<langsyntaxhighlight lang="d">import std.stdio, std.string, std.algorithm, std.path, std.array;
 
string commonDirPath(in string[] paths, in string sep = "/") pure {
Line 570 ⟶ 682:
"/home/user1/tmp/coven/members"];
writeln(`The common path is: "`, paths.commonDirPath, '"');
}</langsyntaxhighlight>
{{out}}
<pre>The common path is: "/home/user1/tmp"</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
<syntaxhighlight lang="delphi">
<lang Delphi>
program Find_common_directory_path;
 
Line 635 ⟶ 747:
'/home/user1/tmp/coven/members']));
Readln;
end.</langsyntaxhighlight>
{{out}}
<pre>/home/user1/tmp</pre>
 
=={{header|EasyLang}}==
{{trans|AWK}}
 
<syntaxhighlight lang=easylang>
func$ comdir path$[] .
for i = 1 to len path$[1]
c$ = substr path$[1] i 1
for j = 2 to len path$[]
if c$ <> substr path$[j] i 1
break 2
.
.
if c$ = "/"
f = i - 1
.
.
return substr path$[1] 1 f
.
a$[] &= "/home/user1/tmp/coverage/test"
a$[] &= "/home/user1/tmp/covert/operator"
a$[] &= "/home/user1/tmp/coven/members"
print comdir a$[]
</syntaxhighlight>
 
=={{header|Elixir}}==
{{trans|Ruby}}
<langsyntaxhighlight lang="elixir">defmodule RC do
def common_directory_path(dirs, separator \\ "/") do
dir1 = Enum.min(dirs) |> String.split(separator)
Line 651 ⟶ 787:
 
dirs = ~w( /home/user1/tmp/coverage/test /home/user1/tmp/covert/operator /home/user1/tmp/coven/members )
IO.inspect RC.common_directory_path(dirs)</langsyntaxhighlight>
 
{{out}}
Line 659 ⟶ 795:
 
=={{header|Erlang}}==
<syntaxhighlight lang="erlang">
<lang Erlang>
-module( find_common_directory ).
 
Line 671 ⟶ 807:
 
keep_common( Components, Acc ) -> [X || X <- Components, Y <- Acc, X =:= Y].
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 679 ⟶ 815:
 
=={{header|F_Sharp|F#}}==
<langsyntaxhighlight lang="fsharp">open System
 
let (|SeqNode|SeqEmpty|) s =
Line 708 ⟶ 844:
 
printfn "The common preffix is: %A" (String.Join("/", (commonPrefix args)))
0</langsyntaxhighlight>
Output for the given task input
<pre>The common preffix is: "/home/user1/tmp"</pre>
 
=={{header|Factor}}==
<langsyntaxhighlight lang="factor">: take-shorter ( seq1 seq2 -- shorter )
[ shorter? ] 2keep ? ;
 
Line 723 ⟶ 859:
 
: common-prefix ( seq separator -- prefix )
[ ] swap '[ _ common-prefix-1 ] map-reduce ;</langsyntaxhighlight>
 
( scratchpad ) {
Line 734 ⟶ 870:
=={{header|FreeBASIC}}==
{{Trans|Visual Basic}}
<langsyntaxhighlight lang="freebasic">
' compile: fbc.exe -s console cdp.bas
 
Line 799 ⟶ 935:
Print : Print "hit any key to end program"
Sleep
End</langsyntaxhighlight>
{{out}}
<pre>/home/user1/tmp/coverage/test
Line 816 ⟶ 952:
/home/user1/tmp/coven/members
/ <- common</pre>
 
=={{header|FutureBasic}}==
<syntaxhighlight lang="futurebasic">
include "NSLog.incl"
 
local fn FindCommonDirectoryPath
CFArrayRef path1 = fn StringComponentsSeparatedByString( @"/home/user1/tmp/coverage/test", @"/" )
CFArrayRef path2 = fn StringComponentsSeparatedByString( @"/home/user1/tmp/covert/operator", @"/" )
CFArrayRef path3 = fn StringComponentsSeparatedByString( @"/home/user1/tmp/coven/members", @"/" )
long i, count = fn ArrayCount( path1 )
CFMutableStringRef mutStr = fn MutableStringWithCapacity( 0 )
for i = 0 to count - 1
if ( fn StringIsEqual( path1[i], path2[i] ) ) and ( fn StringIsEqual( path2[i], path3[i] ) )
MutableStringAppendString( mutStr, fn StringWithFormat( @"%@/\b", path1[i] ) )
else
exit for
end if
next
NSLog( @"%@", mutstr )
end fn
 
fn FindCommonDirectoryPath
 
HandleEvents
</syntaxhighlight>
{{output}}
<pre>
/home/user1/tmp/
</pre>
 
=={{header|Gambas}}==
<langsyntaxhighlight lang="gambas">Public Sub Main()
Dim sFolder As String[] = ["/home/user1/tmp/coverage/test", "/home/user1/tmp/covert/operator", "/home/user1/tmp/coven/members"]
Dim sSame As String
Line 834 ⟶ 1,000:
Print Mid(sSame, 1, RInStr(sSame, "/") - 1)
 
End</langsyntaxhighlight>
Output:
<pre>
Line 845 ⟶ 1,011:
E.g. (<code>/home/user1, /home/user1/foo, /home/user1/bar</code>) should result in <code>/home/user1</code>, not <code>/home</code>.
 
<langsyntaxhighlight lang="go">package main
 
import (
Line 923 ⟶ 1,089:
fmt.Println("Common path:", c)
}
}</langsyntaxhighlight>
 
=={{header|Groovy}}==
Solution:
<langsyntaxhighlight lang="groovy">def commonPath = { delim, Object[] paths ->
def pathParts = paths.collect { it.split(delim) }
pathParts.transpose().inject([match:true, commonParts:[]]) { aggregator, part ->
Line 934 ⟶ 1,100:
aggregator
}.commonParts.join(delim)
}</langsyntaxhighlight>
 
Test:
<langsyntaxhighlight lang="groovy">println commonPath('/',
'/home/user1/tmp/coverage/test',
'/home/user1/tmp/covert/operator',
Line 946 ⟶ 1,112:
'/home/user1/tmp/covert/test',
'/home/user1/tmp/coven/test',
'/home/user1/tmp/covers/test')</langsyntaxhighlight>
 
Output:
Line 955 ⟶ 1,121:
{{works with|GW-BASIC}}
{{works with|Chipmunk Basic}}
{{works with|QBasic}}
 
Because most BASICs don't have any sort of parsing functions built in, we have to deal with the entire string (rather than checking one level at a time).
Line 960 ⟶ 1,127:
Note that if the root directory is the common path, this reports the same as no match found (i.e. blank result).
 
<langsyntaxhighlight lang="qbasic">10 REM All GOTO statements can be replaced with EXIT FOR in newer BASICs.
 
110 X$ = "/home/user1/tmp/coverage/test"
Line 988 ⟶ 1,155:
350 A = L0 - 1
360 P$ = LEFT$(X$, A)
370 PRINT "Common path is '"; P$; "'"</langsyntaxhighlight>
 
Output:
Line 995 ⟶ 1,162:
=={{header|Haskell}}==
 
<langsyntaxhighlight lang="haskell">import Data.List
 
-- Return the common prefix of two lists.
Line 1,017 ⟶ 1,184:
"/home/user1/tmp/covert/operator",
"/home/user1/tmp/coven/members"
]</langsyntaxhighlight>
 
Or, expressed directly in applicative terms:
<langsyntaxhighlight lang="haskell">import Data.List (transpose, intercalate)
import Data.List.Split (splitOn)
 
Line 1,040 ⟶ 1,207:
, "/home/user1/tmp/covert/operator"
, "/home/user1/tmp/coven/members"
]</langsyntaxhighlight>
{{Out}}
<pre>/home/user1/tmp</pre>
 
=={{header|HicEst}}==
<langsyntaxhighlight HicEstlang="hicest">CHARACTER a='/home/user1/tmp/coverage/test', b='/home/user1/tmp/covert/operator', c='/home/user1/tmp/coven/members'
 
minLength = MIN( LEN(a), LEN(b), LEN(c) )
Line 1,058 ⟶ 1,225:
WRITE(Messagebox, Name) "No common directory for", a, b, c
ENDIF
ENDDO</langsyntaxhighlight>
 
=={{header|Icon}} and {{header|Unicon}}==
<langsyntaxhighlight Iconlang="icon">procedure main()
write(lcdsubstr(["/home/user1/tmp/coverage/test","/home/user1/tmp/covert/operator","/home/user1/tmp/coven/members"]))
end
Line 1,080 ⟶ 1,247:
if not match(s,x) then fail
return s
end</langsyntaxhighlight>
 
=={{header|J}}==
'''Solution:'''
<langsyntaxhighlight lang="j">parseDirs =: = <;.2 ]
getCommonPrefix =: {. ;@{.~ 0 i.~ *./@(="1 {.)
 
getCommonDirPath=: [: getCommonPrefix parseDirs&></langsyntaxhighlight>
 
'''Example:'''
<langsyntaxhighlight lang="j"> paths=: '/home/user1/tmp/coverage/test';'/home/user1/tmp/covert/operator';'/home/user1/tmp/coven/members'
getCommonPrefix >paths
/home/user1/tmp/cove
'/' getCommonDirPath paths
/home/user1/tmp/</langsyntaxhighlight>
 
'''Note:'''
This alternative formulation of parseDirs provides cross-platform support, without the need to specify the path separator.
<langsyntaxhighlight lang="j">parseDirs =: (PATHSEP_j_&= <;.2 ])@jhostpath</langsyntaxhighlight>
 
=={{header|Java}}==
{{works with|Java|1.5+}}
This example is case-sensitive.
<langsyntaxhighlight lang="java5">public class CommonPath {
public static String commonPath(String... paths){
String commonPath = "";
Line 1,141 ⟶ 1,308:
System.out.println(commonPath(paths2));
}
}</langsyntaxhighlight>
Output:
<pre>/home/user1/tmp/
Line 1,148 ⟶ 1,315:
 
A slightly modified version of the previous program, only the method commonPath() is changed.
<langsyntaxhighlight lang="java5">
static String commonPath(String... paths){
String commonPath = "";
Line 1,167 ⟶ 1,334:
return commonPath;
}
</syntaxhighlight>
</lang>
 
=={{header|JavaScript}}==
<langsyntaxhighlight lang="javascript">
/**
* Given an array of strings, return an array of arrays, containing the
Line 1,216 ⟶ 1,383:
 
console.log(`Common path is: ${commonPath(cdpInput)}`);
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,224 ⟶ 1,391:
 
=={{header|jq}}==
<langsyntaxhighlight lang="jq"># maximal_initial_subarray takes as input an array of arrays:
def maximal_initial_subarray:
(map( .[0] ) | unique) as $u
Line 1,237 ⟶ 1,404:
[.[] | split(slash)] | maximal_initial_subarray | join(slash) ;
 
common_path("/")</langsyntaxhighlight>
 
Assuming the above jq program is in a file named common_path.jq and that the file directories.txt contains the three given directory strings quoted with double quotation marks:
<langsyntaxhighlight lang="jq">$ jq -s -f common_path.jq directories.txt
"home/user1/tmp"</langsyntaxhighlight>
 
=={{header|Julia}}==
{{works with|Julia|0.6}}
 
<langsyntaxhighlight lang="julia">function commonpath(ds::Vector{<:AbstractString}, dlm::Char='/')
0 < length(ds) || return ""
1 < length(ds) || return String(ds[1])
Line 1,265 ⟶ 1,432:
 
println("Comparing:\n - ", join(test, "\n - "))
println("for their common directory path yields:\n", commonpath(test))</langsyntaxhighlight>
 
{{out}}
Line 1,276 ⟶ 1,443:
 
=={{header|Kotlin}}==
<langsyntaxhighlight lang="scala">// version 1.1.51
 
fun findCommonDirPath(paths: List<String>, separator: Char): String {
Line 1,303 ⟶ 1,470:
println("The common directory path of:\n\n$pathsToPrint\n")
println("is '${findCommonDirPath(paths, '/')}'")
}</langsyntaxhighlight>
 
{{out}}
Line 1,317 ⟶ 1,484:
 
=={{header|Lasso}}==
<langsyntaxhighlight Lassolang="lasso">#!/usr/bin/lasso9
 
local(
Line 1,333 ⟶ 1,500:
}
 
stdoutnl(commonpath(#path1, #path2, #path3))</langsyntaxhighlight>
 
Output:
Line 1,339 ⟶ 1,506:
 
=={{header|Liberty BASIC}}==
<langsyntaxhighlight lang="lb">path$(1) = "/home/user1/tmp/coverage/test"
path$(2) = "/home/user1/tmp/covert/operator"
path$(3) = "/home/user1/tmp/coven/members"
Line 1,363 ⟶ 1,530:
end if
wend
end function</langsyntaxhighlight>
 
=={{header|Lingo}}==
<langsyntaxhighlight lang="lingo">on getCommonPath (pathes, sep)
_player.itemDelimiter = sep
 
Line 1,384 ⟶ 1,551:
end repeat
return pathes[1].item[1..commonCnt]
end</langsyntaxhighlight>
<langsyntaxhighlight lang="lingo">pathes = []
pathes.add("/home/user1/tmp/coverage/test")
pathes.add("/home/user1/tmp/covert/operator")
Line 1,391 ⟶ 1,558:
 
put getCommonPath(pathes, "/")
-- "/home/user1/tmp"</langsyntaxhighlight>
 
=={{header|MapBasic}}==
Line 1,397 ⟶ 1,564:
Derived from the [https://www.rosettacode.org/wiki/Find_common_directory_path#BASIC BASIC] example above
 
<langsyntaxhighlight lang="qbasic">Include "MapBasic.def"
 
Declare Sub Main
Line 1,462 ⟶ 1,629:
PRINT "Common path is " + commonPath(x(), Sep)
 
End Sub</langsyntaxhighlight>
 
=={{header|Maple}}==
<syntaxhighlight lang="maple">
<lang Maple>
dirpath:=proc(a,b,c)
local dirtemp,dirnew,x;
Line 1,475 ⟶ 1,642:
end use;
end proc;
</syntaxhighlight>
</lang>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<langsyntaxhighlight Mathematicalang="mathematica">FindCommonDirectory[x_] := If[StringTake[#, -1] != "/", StringTake[#, Max[StringPosition[#, "/"]]], #] &
[Fold[LongestCommonSubsequence, First[x] , Rest[x]]]
 
FindCommonDirectory[{"/home/user1/tmp/coverage/test", "/home/user1/tmp/covert/operator", "/home/user1/tmp/coven/members"}]
->"/home/user1/tmp/"</langsyntaxhighlight>
 
=={{header|MATLAB}} / {{header|Octave}}==
<syntaxhighlight lang="matlab">
<lang Matlab>
function lcp = longest_common_dirpath(varargin)
ix = find(varargin{1}=='/');
Line 1,497 ⟶ 1,664:
 
longest_common_dirpath('/home/user1/tmp/coverage/test', '/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members')
</syntaxhighlight>
</lang>
 
{{out}}
Line 1,505 ⟶ 1,672:
 
=={{header|Maxima}}==
<langsyntaxhighlight lang="maxima">scommon(a, b) := block([n: min(slength(a), slength(b))],
substring(a, 1, catch(for i thru n do (
if not cequal(charat(a, i), charat(b, i)) then throw(i)), n + 1)))$
Line 1,515 ⟶ 1,682:
 
commonpath(["c:/files/banister.jpg", "c:/files/bank.xls", "c:/files/banana-recipes.txt"]);
"c:/files"</langsyntaxhighlight>
 
=={{header|MUMPS}}==
<syntaxhighlight lang="mumps">FCD
<lang MUMPS>FCD
NEW D,SEP,EQ,LONG,DONE,I,J,K,RETURN
SET D(1)="/home/user1/tmp/coverage/test"
Line 1,532 ⟶ 1,699:
WRITE !,"The longest common directory is: ",RETURN
KILL D,SEP,EQ,LONG,DONE,I,J,K,RETURN
QUIT</langsyntaxhighlight>
Usage:<pre>
USER>D FCD^ROSETTA
Line 1,543 ⟶ 1,710:
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import strutils
 
proc commonprefix(paths: openarray[string], sep = "/"): string =
Line 1,555 ⟶ 1,722:
result = result[0 .. result.rfind(sep)]
 
echo commonprefix(@["/home/user1/tmp/coverage/test", "/home/user1/tmp/covert/operator", "/home/user1/tmp/coven/members"])</langsyntaxhighlight>
Output:
<pre>/home/user1/tmp</pre>
 
=={{header|OCaml}}==
<syntaxhighlight lang="ocaml">let rec common_prefix xs ys = match xs, ys with
| x :: xs, y :: ys when x = y -> x :: common_prefix xs ys
| _ -> []
 
let common_prefix_all = function
<lang ocaml>let rec aux acc paths =
| x :: xs -> List.fold_left common_prefix x xs
if List.mem [] paths
| _ -> []
then (List.rev acc) else
let heads = List.map List.hd paths in
let item = List.hd heads in
let all_the_same =
List.for_all ((=) item) (List.tl heads)
in
if all_the_same
then aux (item::acc) (List.map List.tl paths)
else (List.rev acc)
 
let common_prefixcommon_ancestor ~sep =paths function=
List.map Str.(split_delim (regexp_string sep)) paths
| [] -> invalid_arg "common_prefix"
|> common_prefix_all
| dirs ->
|> String.concat sep
let paths = List.map (Str.split (Str.regexp_string sep)) dirs in
let res = aux [] paths in
(sep ^ (String.concat sep res))
 
let ()_ = assert begin
common_ancestor ~sep:"/" [
let dirs = [
"/home/user1/tmp/coverage/test";
"/home/user1/tmp/covert/operator";
"/home/user1/tmp/coven/members";
] = "/home/user1/tmp"
] in
end</syntaxhighlight>
print_endline (common_prefix "/" dirs);
;;</lang>
 
(usesRequires the modulestandard <code>[httphttps://camlocaml.inria.fr/pub/docsorg/manual-ocaml/libref/Strlibstr.html Strstr]</code>, str.cma)library
 
=={{header|OpenEdge/Progress}}==
<langsyntaxhighlight lang="progress">FUNCTION findCommonDir RETURNS CHAR(
i_cdirs AS CHAR,
i_cseparator AS CHAR
Line 1,622 ⟶ 1,781:
RETURN cresult.
 
END FUNCTION.</langsyntaxhighlight>
 
<langsyntaxhighlight lang="progress">MESSAGE
findCommonDir(
'/home/user1/tmp/coverage/test' + '~n' +
Line 1,631 ⟶ 1,790:
'/'
)
VIEW-AS ALERT-BOX</langsyntaxhighlight>
 
Output
Line 1,645 ⟶ 1,804:
=={{header|Oz}}==
With a few helper functions, we can express the solution like this in Oz:
<langsyntaxhighlight lang="oz">declare
fun {CommonPrefix Sep Paths}
fun {GetParts P} {String.tokens P Sep} end
Line 1,676 ⟶ 1,835:
["/home/user1/tmp/coverage/test"
"/home/user1/tmp/covert/operator"
"/home/user1/tmp/coven/members"]}}</langsyntaxhighlight>
 
=={{header|PARI/GP}}==
<langsyntaxhighlight lang="parigp">cdp(v)={
my(s="");
v=apply(t->Vec(t),v);
Line 1,690 ⟶ 1,849:
if(vecmax(apply(length,v))==vecmin(apply(length,v)),concat(v[1]),s)
};
cdp(["/home/user1/tmp/coverage/test","/home/user1/tmp/covert/operator","/home/user1/tmp/coven/members"])</langsyntaxhighlight>
 
=={{header|Pascal}}==
==={{header|Free Pascal}}===
<syntaxhighlight lang="pascal">
Program CommonPaths;
{$mode ObjFPC}{$H+}
uses
Classes, Math;
 
const
Paths: array of string = ('/home/user1/tmp/coverage/test',
'/home/user1/tmp/covert/operator',
'/home/user1/tmp/coven/members');
 
function FindShortestCommonPath(arr: array of TStringList; shortestPath: Integer): string;
var
i, j: Integer;
commonStr: string;
begin
Result := '/';
if Length(arr) = 0 then
Exit;
for j := 0 to shortestPath - 1 do
begin
commonStr := arr[0][j];
for i := 1 to High(arr) do
begin
if arr[i][j] <> commonStr then
Exit(Result);
end;
Result := Result + commonStr + '/';
end;
end;
var
arr: array of TStringList;
i, shortestpath: uint32;
 
begin
shortestpath := High(uint32);
SetLength(arr, Length(paths));
 
for i := 0 to High(paths) do
begin
arr[i] := TStringList.Create;
arr[i].AddDelimitedText(paths[i], '/', false);
arr[i].Delete(0);
shortestpath := Min(shortestpath, arr[i].Count);
end;
 
Writeln(FindShortestCommonPath(arr, shortestpath));
 
for i := 0 to High(paths) do
arr[i].Free;
end.
</syntaxhighlight>
{{out}}
<pre>
/home/user1/tmp/
</pre>
 
 
 
 
=={{header|Perl}}==
Line 1,696 ⟶ 1,917:
A solution which lets the regex engine do all the work ''(it operates on the concatenation of the given paths delimited by null-bytes, which should be safe since null-bytes are not allowed inside paths)'':
 
<langsyntaxhighlight Perllang="perl">sub common_prefix {
my $sep = shift;
my $paths = join "\0", map { $_.$sep } @_;
$paths =~ /^ ( [^\0]* ) $sep [^\0]* (?: \0 \1 $sep [^\0]* )* $/x;
return $1;
}</langsyntaxhighlight>
 
A more conventional solution, which tallies up all potential prefixes from the given paths and then looks for the longest one that occurred the same number of times as there are paths:
 
<langsyntaxhighlight Perllang="perl">use List::Util qw(first);
 
sub common_prefix {
Line 1,716 ⟶ 1,937:
return first { $prefixes{$_} == @paths } reverse sort keys %prefixes;
}</langsyntaxhighlight>
 
'''Testing:'''
 
<langsyntaxhighlight lang="perl">my @paths = qw(/home/user1/tmp/coverage/test
/home/user1/tmp/covert/operator
/home/user1/tmp/coven/members);
print common_prefix('/', @paths), "\n";</langsyntaxhighlight>
 
{{out}}
Line 1,731 ⟶ 1,952:
Note: if the testset contains /home/user1/tmp the result is /home/user1, with /home/user1/tmp/ instead of that, it is /home/user1/tmp<br>
To change that behaviour, simply remove both the [1..-2]<br>
For cross-platform operation, simply use the split_path and join_path builtins (not pwa/p2js compatible) instead of split and join.
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>function common_directory_path(sequence paths, integer sep='/')
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
sequence res = {}
<span style="color: #008080;">function</span> <span style="color: #000000;">common_directory_path</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">paths</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">sep</span><span style="color: #0000FF;">=</span><span style="color: #008000;">'/'</span><span style="color: #0000FF;">)</span>
if length(paths) then
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
res = split(paths[1],sep)[1..-2]
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">paths</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
for i=2 to length(paths) do
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">paths</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span><span style="color: #000000;">sep</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
sequence pi = split(paths[i],sep)[1..-2]
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">2</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">paths</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
for j=1 to length(res) do
<span style="color: #004080;">sequence</span> <span style="color: #000000;">pi</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">split</span><span style="color: #0000FF;">(</span><span style="color: #000000;">paths</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">],</span><span style="color: #000000;">sep</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
if j>length(pi) or res[j]!=pi[j] then
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
res = res[1..j-1]
<span style="color: #008080;">if</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">pi</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">or</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]!=</span><span style="color: #000000;">pi</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
exit
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">j</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
end if
<span style="color: #008080;">exit</span>
end for
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
if length(res)=0 then exit end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
end for
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end if
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
return join(res,sep)
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
end function
<span style="color: #008080;">return</span> <span style="color: #7060A8;">join</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #000000;">sep</span><span style="color: #0000FF;">)</span>
 
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
constant test = {"/home/user1/tmp/coverage/test",
"/home/user1/tmp/covert/operator",
<span style="color: #008080;">constant</span> <span style="color: #000000;">test</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"/home/user1/tmp/coverage/test"</span><span style="color: #0000FF;">,</span>
"/home/user1/tmp/coven/members"}
<span style="color: #008000;">"/home/user1/tmp/covert/operator"</span><span style="color: #0000FF;">,</span>
?common_directory_path(test)</lang>
<span style="color: #008000;">"/home/user1/tmp/coven/members"</span><span style="color: #0000FF;">}</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">common_directory_path</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 1,760 ⟶ 1,984:
 
=={{header|PHP}}==
<langsyntaxhighlight lang="php"><?php
 
/*
Line 1,816 ⟶ 2,040:
}
 
?></langsyntaxhighlight>
 
 
<langsyntaxhighlight lang="php"><?php
 
/* A more compact string-only version, which I assume would be much faster */
Line 1,840 ⟶ 2,064:
}
 
?></langsyntaxhighlight>
 
=={{header|Picat}}==
Here are two different approaches. Both use <code>append/3</code> for getting the common prefix.
 
===Using maxof/2===
Using <code>maxof/2</code> to get the longest common prefix.
<syntaxhighlight lang="picat">find_common_directory_path(Dirs) = Path =>
maxof( (common_prefix(Dirs, Path,Len), append(_,"/",Path)), Len).
 
%
% Find a common prefix of all lists/strings in Ls.
% Using append/3.
%
common_prefix(Ls, Prefix,Len) =>
foreach(L in Ls)
append(Prefix,_,L)
end,
Len = Prefix.length.</syntaxhighlight>
 
===Mode-directed tabling===
Using mode-directed tabling for maximizing the length.
<syntaxhighlight lang="picat">find_common_directory_path2(Dirs) = Path =>
common_prefix2(Dirs,Path,'/',_Len).
 
table(+,-,max)
common_prefix2(Ls,Prefix,Len) =>
common_prefix2(Ls,Prefix,[],Len).
 
table(+,-,+,max)
common_prefix2(Ls,Prefix,Last,Len) =>
foreach(L in Ls)
append(Prefix,_,L)
end,
if Last != [], Prefix != [] then
Prefix.last() == Last
end,
Len = Prefix.length.</syntaxhighlight>
 
For the directories
<pre>
Dirs = [
"/home/user1/tmp/coverage/test",
"/home/user1/tmp/covert/operator",
"/home/user1/tmp/coven/members"
]
</pre>
 
both find this solution:
<pre>path = /home/user1/tmp/</pre>
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(de commonPath (Lst Chr)
(glue Chr
(make
(apply find
(mapcar '((L) (split (chop L) Chr)) Lst)
'(@ (or (pass <>) (nil (link (next))))) ) ) ) )</langsyntaxhighlight>
Output:
<pre>(commonPath
Line 1,860 ⟶ 2,133:
 
=={{header|Pike}}==
<langsyntaxhighlight Pikelang="pike">array paths = ({ "/home/user1/tmp/coverage/test",
"/home/user1/tmp/covert/operator",
"/home/user1/tmp/coven/members" });
Line 1,870 ⟶ 2,143:
string cp = String.common_prefix(paths);
cp = cp[..sizeof(cp)-search(reverse(cp), "/")-2];
Result: "/home/user1/tmp"</langsyntaxhighlight>
 
=={{header|PowerBASIC}}==
{{Trans|Visual Basic}}
<langsyntaxhighlight lang="powerbasic">#COMPILE EXE
#DIM ALL
#COMPILER PBCC 6
Line 1,941 ⟶ 2,214:
CON.WAITKEY$
 
END FUNCTION</langsyntaxhighlight>
{{out}}
<pre>/home/user1/tmp/coverage/test
Line 1,961 ⟶ 2,234:
=={{header|PowerShell}}==
 
<syntaxhighlight lang="powershell">
<lang Powershell>
<#
.Synopsis
Line 1,989 ⟶ 2,262:
}
}
</syntaxhighlight>
</lang>
 
Sample execution:
<syntaxhighlight lang="text">
"C:\a\b\c\d\e","C:\a\b\e\f","C:\a\b\c\d\x" | Get-CommonPath
C:\a\b
</syntaxhighlight>
</lang>
 
=={{header|Prolog}}==
 
<langsyntaxhighlight lang="prolog">
 
%! directory_prefix(PATHs,STOP0,PREFIX)
Line 2,050 ⟶ 2,323:
.
 
</syntaxhighlight>
</lang>
 
{{out}}
Line 2,063 ⟶ 2,336:
 
Simply by checking the catalog names until they mismatch and add up the correct parts, the task is accomplished.
<langsyntaxhighlight PureBasiclang="purebasic">Procedure.s CommonPath(Array InPaths.s(1),separator.s="/")
Protected SOut$=""
Protected i, j, toggle
Line 2,085 ⟶ 2,358:
Next
ForEver
EndProcedure</langsyntaxhighlight>
 
Example of implementation
<langsyntaxhighlight PureBasiclang="purebasic">Dim t.s(2)
t(0)="/home/user1/tmp/coverage/test"
t(1)="/home/user1/tmp/covert/operator"
t(2)="/home/user1/tmp/coven/members"
 
Debug CommonPath(t(),"/"))</langsyntaxhighlight>
 
=={{header|Python}}==
 
Since Python 3.5 os.path.commonpath function can be used:
<langsyntaxhighlight lang="python">>>> import os
>>> os.path.commonpath(['/home/user1/tmp/coverage/test',
'/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members'])
'/home/user1/tmp'</langsyntaxhighlight>
 
The Python os.path.commonprefix function is [http://nedbatchelder.com/blog/201003/whats_the_point_of_ospathcommonprefix.html broken] as it returns common characters that may not form a valid directory path:
<langsyntaxhighlight lang="python">>>> import os
>>> os.path.commonprefix(['/home/user1/tmp/coverage/test',
'/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members'])
'/home/user1/tmp/cove'</langsyntaxhighlight>
 
This result can be fixed:
<langsyntaxhighlight lang="python">>>> def commonprefix(args, sep='/'):
return os.path.commonprefix(args).rpartition(sep)[0]
 
>>> commonprefix(['/home/user1/tmp/coverage/test',
'/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members'])
'/home/user1/tmp'</langsyntaxhighlight>
 
Even shorter:
<langsyntaxhighlight lang="python">>>> paths = ['/home/user1/tmp/coverage/test', '/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members']
>>> os.path.dirname(os.path.commonprefix(paths))
'/home/user1/tmp'</langsyntaxhighlight>
 
But it may be better to not rely on the faulty implementation at all:
<langsyntaxhighlight lang="python">>>> from itertools import takewhile
>>> def allnamesequal(name):
return all(n==name[0] for n in name[1:])
Line 2,138 ⟶ 2,411:
'/home/user1/tmp/covert/operator', '/home/user1/tmp/coven/members'])
'/home/user1/tmp'
>>> </langsyntaxhighlight>
 
=={{header|Quackery}}==
 
<syntaxhighlight lang="Quackery"> [ over size
over size min
dup dip unrot times
[ over i^ peek
over i^ peek
!= if
[ rot drop
i^ unrot
conclude ] ]
2drop ] is equalto ( $ $ --> n )
 
[ 0 unrot over size
times
[ over i peek
over = if
[ rot drop
i unrot
conclude ] ]
2drop ] is lastof ( $ c --> n )
 
[ swap behead swap
witheach
[ over equalto
split drop ]
dup rot lastof
split drop ] is cdp ( [ c --> n )
 
$ '/home/user1/tmp/coverage/test
/home/user1/tmp/covert/operator
/home/user1/tmp/coven/members' nest$
char / cdp echo$</syntaxhighlight>
 
{{out}}
 
<pre>/home/user1/tmp</pre>
 
=={{header|R}}==
<syntaxhighlight lang="r">
<lang r>
get_common_dir <- function(paths, delim = "/")
{
Line 2,164 ⟶ 2,475:
get_common_dir(paths) # "/home/user1/tmp"
 
</syntaxhighlight>
</lang>
 
=={{header|Racket}}==
<syntaxhighlight lang="racket">
<lang Racket>
#lang racket
 
Line 2,186 ⟶ 2,497:
"/home/user1/tmp/coven/members")
;; --> "/home/user1/tmp"
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" perl6line>my $sep = '/';
my @dirs = </home/user1/tmp/coverage/test
/home/user1/tmp/covert/operator
Line 2,205 ⟶ 2,516:
 
say "The longest common path is $prefix";
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,211 ⟶ 2,522:
</pre>
If you'd prefer a pure FP solution without side effects, you can use this:
<syntaxhighlight lang="raku" perl6line>my $sep := '/';
my @dirs := </home/user1/tmp/coverage/test
/home/user1/tmp/covert/operator
Line 2,222 ⟶ 2,533:
last unless all(@comps[*]»[$column]) eq @comps[0][$column];
take @comps[0][$column] // last;
}</langsyntaxhighlight>
Or here's another factoring, that focuses on building the result with cumulative sequences and getting the solution with `first`:
<syntaxhighlight lang="raku" perl6line>my $sep = '/';
my @dirs = </home/user1/tmp/coverage/test
/home/user1/tmp/covert/operator
Line 2,231 ⟶ 2,542:
sub is_common_prefix { so $^prefix eq all(@dirs).substr(0, $prefix.chars) }
 
say ([\~] @dirs.comb(/ $sep [ <!before $sep> . ]* /)).reverse.first: &is_common_prefix</langsyntaxhighlight>
 
=={{header|REXX}}==
<langsyntaxhighlight lang="rexx">/*REXX program finds the common directory path for a list of files. */
/* original code: Gerard Schildberger @. = /*the default for all file lists (null)*/
/* 20230606 Walter Pachl refurbisher adn improved (file.4 = 'home' -> /) */
@.1 = '/home/user1/tmp/coverage/test'
file. = '' /*the default for all file lists (null)*/
@.2 = '/home/user1/tmp/covert/operator'
@file.31 = '/home/user1/tmp/covencoverage/memberstest'
/*123456789.123456789.123456768*/
L= length(@.1) /*use the length of the first string. */
file.2 = '/home/user1/tmp/covert/operator'
do j=2 while @.j\=='' /*start search with the second string. */
file.3 = '/home/user1/tmp/coven/members'
_= compare(@.j, @.1) /*use REXX compare BIF for comparison*/
if _==0 then iterate /*Strings are equal? Then con't use min*/
L= min(L, _) /*get the minimum length equal strings.*/
if right(@.j, 1)=='/' then iterate /*if a directory, then it's OK. */
L= lastpos('/', left(@.j, L) ) /*obtain directory name up to here*/
end /*j*/
 
commonL= leftlength( @file.1,) lastpos('/', @.1, L) ) /*determineuse the shortestlength of DIRthe first string. */
Do j=2 While file.j\=='' /*loop for the other file names */
if right(common, 1)=='/' then common= left(common, max(0, length(common) - 1) )
diffp=compare(file.j,file.1) /*find the first different character */
if common=='' then common= "/" /*if no common directory, assume home. */
say 'common directoryIf diffp>0 Then Do path: ' common /*Strings are different [↑] handle trailing / delimiter*/
L=min(L,diffp) /*stickget athe forkminimum inlength it,equal we're all donestrings. */</lang>
If right(file.j,1)<>'/' Then Do /*not a directory */
L=lastpos('/',left(file.j,L)) /* go back to directory end */
If L=0 Then Do
Say 'common directory path: /'
Exit
End
End
End
End
common=left(file.1,lastpos('/',file.1,L)) /*determine the shortest DIR string.*/
If right(common,1)=='/' Then /* remove the trailing / */
common=left(common,length(common)-1)
If common=='' then common= "/" /*if no common directory, assume home. */
Say 'common directory path: 'common
/*stick a fork in it, we're all done. */
</syntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 2,259 ⟶ 2,581:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Find common directory path
 
Line 2,284 ⟶ 2,606:
end
return left(p[1], o-1)
</syntaxhighlight>
</lang>
Output:
<pre>
/home/user1/tmp
</pre>
 
=={{header|RPL}}==
{{works with|HP|48}}
≪ DUP SIZE → paths n
≪ paths n GET "/" +
'''WHILE''' 'n' DECR '''REPEAT'''
paths n GET "/" +
DUP2 SIZE SWAP SIZE MIN DUP
1 SWAP '''FOR''' j
DROP
OVER j DUP SUB OVER j DUP SUB ≠
j
'''IF''' SWAP '''THEN''' DUP 1 ≠ - OVER SIZE 'j' STO '''END'''
'''NEXT'''
1 SWAP SUB SWAP DROP
'''END'''
DUP SIZE
'''WHILE''' DUP2 DUP SUB "/" ≠ '''REPEAT''' 1 - '''END'''
DUP 1 ≠ -
1 SWAP SUB
≫ ≫ '<span style="color:blue">CPATH</span>' STO
 
{ "/home/user1/tmp/coverage/test" "/home/user1/tmp/covert/operator" "/home/user1/tmp/coven/members" } <span style="color:blue">CPATH</span>
{{out}}
<pre>
1: "/home/user1/tmp"
</pre>
 
Line 2,293 ⟶ 2,642:
Uses the standard library <code>[http://www.ruby-doc.org/stdlib/libdoc/abbrev/rdoc/index.html abbrev]</code> module: Given a set of strings, calculate the set of unambiguous abbreviations for those strings, and return a hash where the keys are all the possible abbreviations and the values are the full strings.
 
<langsyntaxhighlight lang="ruby">require 'abbrev'
 
dirs = %w( /home/user1/tmp/coverage/test /home/user1/tmp/covert/operator /home/user1/tmp/coven/members )
 
common_prefix = dirs.abbrev.keys.min_by {|key| key.length}.chop # => "/home/user1/tmp/cove"
common_directory = common_prefix.sub(%r{/[^/]*$}, '') # => "/home/user1/tmp"</langsyntaxhighlight>
 
Implementing without that module:
<langsyntaxhighlight lang="ruby">separator = '/'
path0, *paths = dirs.collect {|dir| dir.split(separator)}
uncommon_idx = path0.zip(*paths).index {|dirnames| dirnames.uniq.length > 1}
uncommon_idx = path0.length unless uncommon_idx # if uncommon_idx==nil
common_directory = path0[0...uncommon_idx].join(separator) # => "/home/user1/tmp"</langsyntaxhighlight>
 
or method version
<langsyntaxhighlight lang="ruby">def common_directory_path(dirs, separator='/')
dir1, dir2 = dirs.minmax.map{|dir| dir.split(separator)}
dir1.zip(dir2).take_while{|dn1,dn2| dn1==dn2}.map(&:first).join(separator)
end
 
p common_directory_path(dirs) #=> "/home/user1/tmp"</langsyntaxhighlight>
 
=={{header|Run BASIC}}==
<langsyntaxhighlight lang="runbasic">' ------------------------------------------
' Find common directory to all directories
' and directories common with other Paths
Line 2,401 ⟶ 2,750:
html "</TABLE>"
wait
end</langsyntaxhighlight>
========= Common paths ================<br />
shows only the first few common paths..
Line 2,442 ⟶ 2,791:
Rust has specific types for owned and borrowed paths. PathBuf is an 'owned' pointer to a path, Path is a borrow; this is similar to String and str, respectively.
 
<syntaxhighlight lang="rust">
<lang Rust>
use std::path::{Path, PathBuf};
 
Line 2,493 ⟶ 2,842:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Scala}}==
===Naive===
This simple solution solves the task as given, but has oddities for edge cases due to the implementation of java.lang.String#split.
<langsyntaxhighlight Scalalang="scala">object FindCommonDirectoryPath extends App {
def commonPath(paths: List[String]): String = {
def common(a: List[String], b: List[String]): List[String] = (a, b) match {
Line 2,514 ⟶ 2,863:
)
println(commonPath(test))
}</langsyntaxhighlight>
Output:
<pre>/home/user1/tmp</pre>
===Advanced===
This implementation will handle various edge cases and relative paths. It also includes any common trailing '/' but callers can remove this if desired.
<langsyntaxhighlight Scalalang="scala">object FindCommonDirectoryPathRelative extends App {
def commonPath(paths: List[String]): String = {
val SEP = "/"
Line 2,568 ⟶ 2,917:
assert(commonPath(List("/a/a/", "/a/b/")) == "/a/")
assert(commonPath(List("/a/b/", "/a/b/")) == "/a/b/")
}</langsyntaxhighlight>
 
=={{header|Seed7}}==
Line 2,578 ⟶ 2,927:
but they need to make sure that a path does not end with a slash.
 
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const func integer: commonLen (in array string: names, in char: sep) is func
Line 2,619 ⟶ 2,968:
writeln("Common path: " <& names[1][.. length]);
end if;
end func;</langsyntaxhighlight>
 
Output:
Line 2,627 ⟶ 2,976:
 
=={{header|Sidef}}==
<langsyntaxhighlight lang="ruby">var dirs = %w(
/home/user1/tmp/coverage/test
/home/user1/tmp/covert/operator
Line 2,635 ⟶ 2,984:
var unique_pref = dirs.map{.split('/')}.abbrev.min_by{.len};
var common_dir = [unique_pref, unique_pref.pop][0].join('/');
say common_dir; # => /home/user1/tmp</langsyntaxhighlight>
 
=={{header|Standard ML}}==
<langsyntaxhighlight lang="sml">fun takeWhileEq ([], _) = []
| takeWhileEq (_, []) = []
| takeWhileEq (x :: xs, y :: ys) =
Line 2,658 ⟶ 3,007:
]
 
val () = print (commonPath #"/" paths ^ "\n")</langsyntaxhighlight>
 
=={{header|Swift}}==
Line 2,664 ⟶ 3,013:
The below solution works only in swift in Linux.
 
<langsyntaxhighlight lang="swift">import Foundation
 
 
Line 2,680 ⟶ 3,029:
 
var output:String = getPrefix(test)!
print(output)</langsyntaxhighlight>
 
===Works on MacOS===
<syntaxhighlight lang="swift">
import Foundation
 
func commonPrefix<T: Equatable>(_ lhs: [T], _ rhs: [T]) -> [T] {
for tryLen in (0...min(lhs.count,rhs.count)).reversed() {
if lhs.starts(with: rhs.prefix(tryLen)) {
return Array<T>(rhs.prefix(tryLen))
}
}
return []
}
 
var test = ["/home/user1/tmp/coverage/test",
"/home/user1/tmp/covert/operator",
"/home/user1/tmp/coven/members"]
 
let lcp: String = test.reduce("") { lhs, rhs in
if !lhs.isEmpty {
var commonSoFar = commonPrefix(
lhs.components(separatedBy: "/"),
rhs.components(separatedBy: "/")
)
return commonSoFar.joined(separator: "/")
}
return rhs
}
print("Longest common path: \(lcp)")
 
// Longest common path: /home/user1/tmp
</syntaxhighlight>
 
=={{header|Tcl}}==
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
proc pop {varname} {
upvar 1 $varname var
Line 2,701 ⟶ 3,082:
}
return [join $parts $separator]
}</langsyntaxhighlight>
 
<pre>% common_prefix {/home/user1/tmp/coverage/test /home/user1/tmp/covert/operator /home/user1/tmp/coven/members}
Line 2,707 ⟶ 3,088:
 
=={{header|TUSCRIPT}}==
<langsyntaxhighlight lang="tuscript">
$$ MODE TUSCRIPT
common=""
Line 2,722 ⟶ 3,103:
ENDIF
ENDLOOP
</syntaxhighlight>
</lang>
Output:
<pre>
Line 2,730 ⟶ 3,111:
=={{header|UNIX Shell}}==
The following is a pure Bourne Shell solution. The while loop controls the maximum depth to check paths.
<langsyntaxhighlight lang="bash">
#!/bin/sh
 
Line 2,751 ⟶ 3,132:
i=`expr $i + 1`
done
</syntaxhighlight>
</lang>
 
=={{header|Ursala}}==
The algorithm is to lex the paths into component directory names, and then find the greatest common prefix of those.
<langsyntaxhighlight Ursalalang="ursala">#import std
 
comdir"s" "p" = mat"s" reduce(gcp,0) (map sep "s") "p"</langsyntaxhighlight>
where <code>"s"</code> is a dummy variable representing the separator, <code>"p"</code> is a dummy variable representing the list of paths, and
*<code>sep</code> is second order function in the standard library that takes a separator character and returns a lexer mapping a string containing the separator to a list of the substrings found between occurrences of it
Line 2,765 ⟶ 3,146:
*<code>mat</code> is a second order function in the standard library that takes a separator character and returns a function that flattens a list of strings into a single string with copies of the separator inserted between them
Here is a version using operators instead of mnemonics for <code>map</code> and <code>reduce</code>.
<langsyntaxhighlight Ursalalang="ursala">comdir"s" "p" = mat"s" gcp:-0 sep"s"* "p"</langsyntaxhighlight>
Here is one in partly point-free form, using the composition operator (<code>+</code>).
<langsyntaxhighlight Ursalalang="ursala">comdir"s" = mat"s"+ gcp:-0+ sep"s"*</langsyntaxhighlight>
Here it is in point-free form.
<langsyntaxhighlight Ursalalang="ursala">comdir = +^/mat gcp:-0++ *+ sep</langsyntaxhighlight>
test program:
<langsyntaxhighlight Ursalalang="ursala">#cast %s
 
test =
Line 2,778 ⟶ 3,159:
'/home/user1/tmp/coverage/test',
'/home/user1/tmp/covert/operator',
'/home/user1/tmp/coven/members'></langsyntaxhighlight>
output:
<pre>'/home/user1/tmp'</pre>
Line 2,786 ⟶ 3,167:
=={{header|VBScript}}==
{{works with|Windows Script Host|*}}
<syntaxhighlight lang="vbscript">
<lang VBScript>
' Read the list of paths (newline-separated) into an array...
strPaths = Split(WScript.StdIn.ReadAll, vbCrLf)
Line 2,818 ⟶ 3,199:
' Remove the final "/"...
WScript.Echo Left(strPath, Len(strPath) - 1)
</syntaxhighlight>
</lang>
 
=={{header|Visual Basic}}==
Line 2,825 ⟶ 3,206:
{{works with|VBA|6.5}}
{{works with|VBA|7.1}}
<langsyntaxhighlight lang="vb">Public Function CommonDirectoryPath(ParamArray Paths()) As String
Dim v As Variant
Dim Path() As String, s As String
Line 2,884 ⟶ 3,265:
"/"
 
End Sub</langsyntaxhighlight>
 
=={{header|Wren}}==
<langsyntaxhighlight ecmascriptlang="wren">var findCommonDir = Fn.new { |paths, sep|
var count = paths.count
if (count == 0) return ""
Line 2,916 ⟶ 3,297:
]
System.write("The common directory path is: ")
System.print(findCommonDir.call(paths, "/"))</langsyntaxhighlight>
 
{{out}}
Line 2,922 ⟶ 3,303:
The common directory path is: /home/user1/tmp
</pre>
 
=={{header|Yabasic}}==
{{trans|GW-BASIC}}
<syntaxhighlight lang="yabasic">x$ = "/home/user1/tmp/coverage/test"
y$ = "/home/user1/tmp/covert/operator"
z$ = "/home/user1/tmp/coven/members"
 
a = len(x$)
if a > len(y$) a = len(y$)
if a > len(z$) a = len(z$)
for i = 1 to a
if mid$(x$, i, 1) <> mid$(y$, i, 1) break
next i
a = i - 1
 
for i = 1 to a
if mid$(x$, i, 1) <> mid$(z$, i, 1) break
next i
a = i - 1
 
if mid$(x$, i, 1) <> "/" then
for i = a to 1 step -1
if "/" = mid$(x$, i, 1) break
next i
fi
 
REM Task description says no trailing slash, so...
a = i - 1
print "Common path is '", left$(x$, a), "'"</syntaxhighlight>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">dirs:=T("/home/user1/tmp/coverage/test", "/home/user1/tmp/covert/operator",
"/home/user1/tmp/coven/members");
n:=Utils.zipWith('==,dirs.xplode()).find(False); // character pos which differs
n=dirs[0][0,n].rfind("/"); // find last "/"
dirs[0][0,n];</langsyntaxhighlight>
{{out}}
<pre>
43

edits