주어진 경로의 모든 상위 디렉토리 경로를 얻으려면 무엇을 사용할 수 있습니까?

주어진 경로의 모든 상위 디렉토리 경로를 얻으려면 무엇을 사용할 수 있습니까?

나는 주어진 경로에 대한 상위 디렉터리 목록을 제공할 수 있는 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

따라서 임시 디렉터리 구조를 만든 다음 찾기를 사용하여 탐색할 수 있습니다.

답변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자동화된 프로세스에서 사용하려면 이를 사용해야 합니다. \0Unix 파일 이름에 포함되지 않는 것이 보장되는 유일한 문자입니다.

단지 재귀적으로 사용됩니다 . dirnames특정 을 제거/활성화하여 printf조정할 수 있습니다. 위 또는 아래로 이동하거나 루트 노드( .또는 /)를 표시하지 않도록 합니다. 귀하의 예에는 루트 노드가 표시되지 않았지만 필요하다고 생각합니다. 이것이 없으면 /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/

관련 정보