假设输入参数是几个文件的FULL路径。说,

/abc/def/file1
/abc/def/ghi/file2
/abc/def/ghi/file3
  • 如何在bash shell脚本中获取目录名称/abc/def
  • 如何仅获取file1/ghi/file2/ghi/file3
  • 最佳答案

    给定第1部分的答案(通用前缀),第2部分的答案很简单;您可以将前缀切成每个名称,这可以通过sed和其他选项来完成。

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

    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
    

    最长的公共(public)前缀/abc/def/abc/def/ghi是吗?我将假定最长的公共(public)前缀是/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
    

    关于bash shell脚本查找几个文件的最接近的父目录,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12340846/

    10-15 02:22