디렉토리의 하위 디렉토리를 나열하는 방법은 무엇입니까?

디렉토리의 하위 디렉토리를 나열하는 방법은 무엇입니까?

특정 경로의 하위 디렉터리를 나열해야 합니다. 구분은 개행 문자가 아닌 공백으로 이루어져야 합니다.

또한 하위 디렉터리에 대한 절대 경로는 원하지 않고 해당 이름만 필요합니다.

# correct
dir1 dir2 dir3

# incorrect: separation with new lines
dir1
dir2
dir3

# incorrect: absolute paths
/home/x/y/dir1 /home/x/y/dir2 /home/x/y/dir3

다른 글도 많이 봤지만이 게시물, 하지만 그들은 내 요청을 이행하지 않았습니다.

나는 이것을 시도했지만 ls -d ~/y새 줄로 구분된 절대 경로를 나열합니다. 나는 sed를 사용하여 경로에서 관련 없는 부분을 제거한 다음 모든 새 줄을 제거할 수 있다고 생각했습니다. 하지만 작동시킬 수 없습니다. 더 나은 솔루션이 있어야 할 것 같습니다.

답변1

GNU 도구를 사용한다고 가정하면 GNU를 사용하여 basename특정 디렉터리에 있는 모든 하위 디렉터리의 이름을 가져올 수 있습니다. 그런 다음 paste공백으로 구분된 목록으로 형식을 지정할 수 있습니다 .

basename -a /some/path/*/ | paste -d ' ' -s -

위 명령은 GNU가 명령줄에서 피연산자로 주어진 여러 경로 이름 중 파일 이름 부분을 반환할 수 basename있다는 사실을 이용합니다 .-a

로 끝나는 파일 일치 패턴을 사용하여 /GNU 경로 이름을 생성합니다 basename. 디렉터리만 이러한 패턴과 일치할 수 있습니다.

마지막으로 pasteGNU에서 생성된 줄 바꿈으로 구분된 목록에서 공백으로 구분된 목록을 만듭니다 basename.

원래 디렉터리 이름에 공백 문자가 포함되어 있으면 결과 파일 이름 목록을 구문 분석하기가 어렵습니다.

디렉토리에 심볼릭 링크가 포함된 경우 이 메서드는 해당 심볼릭 링크를 따르려고 시도합니다.


외부 도구의 사용을 제한하기 위해 셸의 배열을 사용하여 bash디렉터리 경로를 저장하고 조작할 수 있습니다.

shopt -s nullglob

topdir=/some/path

dirpaths=( "$topdir"/*/ )
dirpaths=( "${dirpaths[@]#$topdir/}" )
dirpaths=( "${dirpaths[@]%/}" )

printf '%s\n' "${dirpaths[*]}"

위의 셸 코드는 이 답변의 첫 번째 부분에서 사용한 것과 동일한 와일드카드 패턴을 확장하지만 결과 디렉터리 경로를 배열에 저장합니다 dirpaths. 그런 다음 $topdir/배열의 각 요소와 뒤따르는 요소에서 알려진 접두사를 제거한 다음 /배열을 공백으로 구분된 이름의 단일 문자열로 인쇄합니다. 마지막 줄의 이름 사이에 사용되는 구분 기호는 $IFS기본적으로 공백인 첫 번째 문자입니다.


를 사용하면 find최상위 디렉터리 자체가 반환되지 않도록 하면서 관심 있는 특정 최상위 디렉터리 내의 하위 디렉터리를 찾을 수 있습니다. 또한 하위 디렉터리 입력도 중지됩니다 find.

topdir=/some/path
find "${topdir%/}/." ! -name . -prune -type d -exec basename {} \; | paste -d ' ' -s -

위의 명령은 시작점 검색을 피하기 위해 네거티브 테스트를 사용 -name하고 검색 트리를 정리하여 하위 디렉터리로 반복되지 않도록 합니다 -prune. 발견된 각 디렉토리를 find호출하여 basename디렉토리의 파일 이름을 별도의 줄에 출력합니다. 마지막 단계로 find결과를 파이프하여 paste한 줄에 공백으로 구분된 목록으로 출력 형식을 지정합니다.

GNU를 사용하면 find다음과 같이 작성할 수 있습니다.

find /some/path -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | paste -d ' ' -s -

이와 같이 사용하면 find숨겨진 이름이 있는 디렉토리가 나열되며 심볼릭 링크된 디렉토리는 표시되지 않습니다.


셸 에서는 zsh고급 셸 글로빙 모드를 사용하여 디렉터리의 파일 이름만 선택하고 한 번에 모두 인쇄할 수 있습니다.

print -r -- /some/path/*(/:t)

/:t이 명령은 두 부분으로 구성되고 이전 globbing 모드에 영향을 미치는 glob 한정자를 사용합니다 /some/path/*. 생성된 각 경로 이름의 파일 이름 부분인 "꼬리"를 추출하는 동안 /패턴이 디렉터리(심볼릭 링크된 디렉터리가 아님, 해당 목적을 위해 -/) 만 일치하도록 만듭니다 .:t

이 명령은 확장된 데이터에서 print -r이스케이프 시퀀스(예: 또는 )를 피하면서 인수를 인쇄하기 위해 공백을 구분 기호로 사용합니다 . 구분된 옵션(쉘 의 작업 에도 적용됨)에 피연산자를 사용하면 glob 확장으로 생성된 디렉터리 이름이 로 시작하더라도 옵션으로 처리되지 않습니다 .\n\t---ksh-

bash셸에서 이를 사용하여 목록을 생성 할 수 있습니다 .

zsh -c 'print -r -- /some/path/*(/:t)'

답변2

하위 디렉터리를 나열하려는 디렉터리를 이미 알고 있으므로 다음을 사용할 수 있습니다.

find /home/x/y -maxdepth 1 -type d -printf '%P '

답변3

for루프 사용에 대한 제안 은 다음과 같습니다 .

$ echo "$(for node in $(ls ~/); do if test -d "${node}"; then printf "${node} "; fi; done)"
Desktop Documents Downloads Music Pictures Public Templates Videos

대체 용도 find:

$ echo "$(for node in $(find ~/ -mindepth 1 -maxdepth 1 -type d); do printf "$(basename ${node}) "; done)"
.mozilla Videos Pictures Music Documents Public Templates Downloads .gnupg .config .local .cache Desktop

편집하다:~에 대한그들을IFS설명했듯이 공백이 있는 디렉터리의 변수를 변경해야 합니다 .

$ IFS_orig=${IFS}
$ IFS=$'\n'
$ echo "$(for node in $(ls ~/); do if test -d "${node}"; then printf "'${node}' "; fi; done)"
'Desktop' 'Documents' 'Downloads' 'Music' 'My Test' 'Pictures' 'Public' 'Templates' 'Videos'

$ IFS=${IFS_orig}

편집하다:가장 쉬운 옵션은 다음을 사용하는 것 같습니다 ls -d *.

$ ls -d *
 Desktop   Documents   Downloads   Music  'My Test'   Pictures   Public   Templates   Videos

또한 for루프 에서는 test절대 경로나 상대 경로를 사용해야 한다는 점을 잊어버리십시오.

$ echo "$(for node in $(ls "${HOME}"); do if test -d "${HOME}/${node}"; then printf "'${node}' "; fi; done)"
'Desktop' 'Documents' 'Downloads' 'Music' 'My Test' 'Pictures' 'Public' 'Templates' 'Videos'

답변4

내가 받은 마지막 명령은 다음과 같습니다.ls -d ~/y/*/ | awk -F/ '{print$5}' | sed 's/ /\\ /' | tr '\n' ' '

출처는 현재 게시물을 삭제한 사용자로부터 왔지만 현재 디렉터리에서 ls를 사용하지 않는다는 점을 고려하지 않았기 때문에 이를 조정했습니다. 또한 공백이 포함된 디렉터리 이름에 백슬래시를 추가하도록 sed 파이프를 추가했습니다.

상당히 하드코딩되어 있어 디렉토리 내의 디렉토리 print$5에만 작동합니다 .~

관련 정보