我可以使用什么来获取给定路径的所有父目录的路径

我可以使用什么来获取给定路径的所有父目录的路径

我正在寻找一个可以从 bash 脚本使用的工具,它可以为我提供给定路径的父目录列表。

foo/bar/moocow例如,给出我想输出的输入:

foo
foo/bar
foo/bar/moocow

如果我可以输入多个路径并获得唯一的结果,那就太好了,例如:

toolimlookingfor << EOF
dir1/file1
dir1/file2
foo/bar/moocow
EOF

输出:

dir1
dir1/file1
dir1/file2
foo
foo/bar
foo/bar/moocow

dirname与我正在寻找的很接近,但它只给出了直接父级。我正在寻找自己和所有父母的道路。

答案1

如果您同意在/tmp文件夹中创建新目录,则可以使用 find 命令,此方法还将负责仅打印唯一的目录名称。

#!/bin/bash
if [[ $# -eq 0 ]]; then exit; fi
mkdir -p /tmp/printnames
for i
do
  mkdir -p /tmp/printnames/"$i"
done
cd /tmp/printnames
find *  -type d -print
rm -r /tmp/printnames

因此,您可以创建一个临时目录结构,然后使用 find 遍历它。

答案2

使用标准的 Python 脚本pathlib模块,处理参数而不是输入:

#! /usr/bin/env python3

import sys

from collections import OrderedDict
from pathlib import Path

paths = OrderedDict()  # to maintain ordering and skip duplicates

for arg in sys.argv[1:]:
    path = Path(arg)
    for subpath in reversed(path.parents):
        # add the parents
        paths[subpath.as_posix()] = subpath
    # add the path itself
    paths[path.as_posix()] = path

# we don't need '.' in the output
if '.' in paths:
    paths.pop('.')

print('\n'.join(paths.keys()))

(可以通过循环轻松地将其修改为使用标准输入sys.stdin。)

例子:

% ./foo.py dir1/file1 dir1/file2 foo/bar/moocow
dir1
dir1/file1
dir1/file2
foo
foo/bar
foo/bar/moocow

答案3

这段代码就可以做到。它不使用临时文件。它适用于空白,但换行符不明确(更改\n\0修复)。\0如果要在自动化流程中使用它,则应该使用它。\0是唯一保证不在 Unix 文件名中的字符。

它只是递归地使用dirnames.您可以通过删除/启用某些printfs 来调整它。使其上升或下降,或不显示根节点(./)。您的示例中没有显示根节点,但我认为这是必要的。如果没有它,/a/b/c输出与 相同a/b/c

#!/bin/bash

function dirnames {
    local input
    local parent
    input="$1"
    if [[ "$input" == "" ]]
    then
        true
    elif [[ "$input" == "." ||  "$input" == "/" ]]
    then
        printf '%s\n' "$input" #print the root node
    else
        #printf '%s\n' "$input"  #print node (descending)
        parent="$(dirname "$input")"
        dirnames "$parent"
        printf '%s\n' "$input" #print node (ascending)
    fi
}

for d in "$@"
do
    dirnames "$d"
done

用法示例

%↳ ./dirnames a/b/c
.
a
a/b
a/b/c
%↳ ./dirnames /a/b/c
/
/a
/a/b
/a/b/c
%↳

为了让它像这样工作

%↳ ./dirnames a/b/c
.
a
b
c
%↳ ./dirnames /a/b/c
/
a
b
c
%↳

然后将文件另存为dirnames然后运行sed -r -i '17 s/("[$]input")/"$(basename \1)"/' dirnames。现在您将拥有一个仅输出每个级别的叶子的脚本。

答案4

如果尾部斜杠(或其他分隔符)适合您,就像我的情况一样,以下解决方案对我来说是最简单、最透明的解决方案:

pth='one/two/three'
sep='/'

# split string into array by separator
arr=($(echo $pth | tr $sep '\n'))

# loop over array and append
sub=''
for index in ${!arr[@]}
do
    sub+="${arr[index]}$sep"
    printf "$index \t ${arr[index]} \t $sub \n"
done

输出:

0        one     one/
1        two     one/two/
2        three   one/two/three/

相关内容