bash shell脚本找到几个文件最近的父目录

假设输入参数是几个文件的FULL路径.说,
/abc/def/file1
/abc/def/ghi/file2
/abc/def/ghi/file3

>如何在bash shell脚本中获取目录名/ abc / def?
>我怎样才能获得file1,/ ghi / file2和/ ghi / file3?

鉴于第1部分(公共前缀)的答案,第2部分的答案是直截了当的;你将每个名字的前缀切掉,这可以用sed和其他选项完成.

然后,有趣的部分是找到共同的前缀.最小公共前缀是/(例如,对于/ etc / passwd和/ bin / sh).最大公共前缀(根据定义)存在于所有字符串中,因此我们只需将其中一个字符串拆分为段,并将可能的前缀与其他字符串进行比较.概述:

split name A into components
kNown_prefix="/"
for each extra component from A
do
    possible_prefix="$kNown_prefix/$extra/"
    for each name
    do
        if $possible_prefix is not a prefix of $name
        then ...all done...break outer loop...
        fi
    done
    ...got here...possible prefix is a prefix!
    kNown_prefix=$possible_prefix
done

有一些管理细节要处理,例如名称中的空格.还有什么是允许的武器.问题是标记为bash但允许哪些外部命令(例如Perl)?

一个未定义的问题 – 假设名称列表是:

/abc/def/ghi
/abc/def/ghi/jkl
/abc/def/ghi/mno

是最长的共同前缀/ abc / def还是/ abc / def / ghi?我假设这里最长的公共前缀是/ abc / def. (如果你真的希望它是/ abc / def / ghi,那么使用/ abc / def / ghi /.作为第一个名字.)

此外,还有调用详细信息:

>如何调用函数或命令?
>如何返回值?
>这是一个或两个函数或命令(longest_common_prefix和’path_without_prefix`)?

两个命令更容易:

> prefix = $(longest_common_prefix name1 [name2 …])
> suffix = $(path_without_prefix / pre / fix / pre / fix / to / file […])

path_without_prefix命令会删除前缀(如果存在),如果前缀未启动名称,则保留参数不变.

longest_common_prefix

longest_common_prefix()
{
    declare -a names
    declare -a parts
    declare i=0

    names=("$@")
    name="$1"
    while x=$(dirname "$name"); [ "$x" != "/" ]
    do
        parts[$i]="$x"
        i=$(($i + 1))
        name="$x"
    done

    for prefix in "${parts[@]}" /
    do
        for name in "${names[@]}"
        do
            if [ "${name#$prefix/}" = "${name}" ]
            then continue 2
            fi
        done
        echo "$prefix"
        break
    done
}

测试:

set -- "/abc/def/file 0" /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3 "/abc/def/ghi/file 4"
echo "Test: $@"
longest_common_prefix "$@"
echo "Test: $@" abc/def
longest_common_prefix "$@" abc/def
set --  /abc/def/ghi/jkl /abc/def/ghi /abc/def/ghi/mno
echo "Test: $@"
longest_common_prefix "$@"
set -- /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3
echo "Test: $@"
longest_common_prefix "$@"
set -- "/a c/d f/file1" "/a c/d f/ghi/file2" "/a c/d f/ghi/file3"
echo "Test: $@"
longest_common_prefix "$@"

输出

Test: /abc/def/file 0 /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3 /abc/def/ghi/file 4
/abc/def
Test: /abc/def/file 0 /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3 /abc/def/ghi/file 4 abc/def
Test: /abc/def/ghi/jkl /abc/def/ghi /abc/def/ghi/mno
/abc/def
Test: /abc/def/file1 /abc/def/ghi/file2 /abc/def/ghi/file3
/abc/def
Test: /a c/d f/file1 /a c/d f/ghi/file2 /a c/d f/ghi/file3
/a c/d f

path_without_prefix

path_without_prefix()
{
    local prefix="$1/"
    shift
    local arg
    for arg in "$@"
    do
        echo "${arg#$prefix}"
    done
}

测试:

for name in /pre/fix/abc /pre/fix/def/ghi /usr/bin/sh
do
    path_without_prefix /pre/fix $name
done

输出

abc
def/ghi
/usr/bin/sh

相关文章

用的openwrt路由器,家里宽带申请了动态公网ip,为了方便把2...
#!/bin/bashcommand1&command2&wait从Shell脚本并行...
1.先查出MAMP下面集成的PHP版本cd/Applications/MAMP/bin/ph...
1、先输入locale-a,查看一下现在已安装的语言2、若不存在如...
BashPerlTclsyntaxdiff1.进制数表示Languagebinaryoctalhexa...
正常安装了k8s后,使用kubect工具后接的命令不能直接tab补全...