특정 경로의 하위 디렉터리를 나열해야 합니다. 구분은 개행 문자가 아닌 공백으로 이루어져야 합니다.
또한 하위 디렉터리에 대한 절대 경로는 원하지 않고 해당 이름만 필요합니다.
# 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
. 디렉터리만 이러한 패턴과 일치할 수 있습니다.
마지막으로 paste
GNU에서 생성된 줄 바꿈으로 구분된 목록에서 공백으로 구분된 목록을 만듭니다 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
에만 작동합니다 .~