위치, 폭이 먼저 모든 디렉토리를 재귀 적으로 나열하려면 어떻게해야합니까?
문제
폭이 먼저 목록이 중요합니다. 또한 검색 된 깊이를 제한하는 것이 좋을 것입니다.
$ find . -type d
/foo
/foo/subfoo
/foo/subfoo/subsub
/foo/subfoo/subsub/subsubsub
/bar
/bar/subbar
$ find . -type d -depth
/foo/subfoo/subsub/subsubsub
/foo/subfoo/subsub
/foo/subfoo
/foo
/bar/subbar
/bar
$ < what goes here? >
/foo
/bar
/foo/subfoo
/bar/subbar
/foo/subfoo/subsub
/foo/subfoo/subsub/subsubsub
가능하면 Bash One-Liner를 사용 하여이 작업을 수행하고 싶습니다. 자바 스크립트 쉘이 있다면
bash("find . -type d").sort( function (x) x.findall(/\//g).length; )
해결책
그만큼 find
명령 지원 -printf
많은 자리 표시자를 인식하는 옵션.
그러한 자리 표시 자 중 하나입니다 %d
주어진 경로의 깊이를 어디에 상대적으로 렌더링하는 find
시작.
따라서 간단한 1 라이너를 사용할 수 있습니다.
find -type d -printf '%d\t%P\n' | sort -r -nk1 | cut -f2-
그것은 매우 간단하며 무거운 툴링에 의존하지 않습니다. perl
.
작동 방식 :
- 내부적으로 파일 목록을 생성하고 각각 2 장 라인으로 렌더링됩니다.
- 첫 번째 필드에는 깊이가 포함되어 있으며 (역) 수치 정렬에 사용 된 다음 잘라냅니다.
- 결과는 간단한 파일 목록, 최초의 최초의 순서로 한 줄 당 하나의 파일입니다.
다른 팁
표준 도구를 사용하여 수행하려면 다음 파이프 라인이 작동해야합니다.
find . -type d | perl -lne 'print tr:/::, " $_"' | sort -n | cut -d' ' -f2
그건,
- 여기에서 모든 디렉토리를 깊이있는 첫 번째 주문으로 찾아 인쇄하십시오.
- 각 디렉토리의 슬래시 수를 계산하고 경로로 전제하십시오.
- 깊이별로 정렬 (즉, 슬래시 수)
- 길을 추출하십시오.
발견 된 깊이를 제한하려면 -maxdepth 인수를 찾은 명령에 추가하십시오.
출력을 찾는 동일한 순서로 나열된 디렉토리를 원한다면 "Sort -n"대신 "Sort -n -s"를 사용하십시오. "-s"플래그는 정렬을 안정화시킵니다 (즉, 동일하게 비교하는 항목들 사이에 입력 순서가 보존됩니다).
디렉토리 계층을 통과 할 때 하향식 또는 상향식으로 깊이있는 첫 번째 검색을 원하기 때문에 내장 유틸리티를 사용하여 할 수 있다고 생각하지 않습니다. 다음은 폭이 큰 검색을 제공하는 파이썬 스크립트입니다.
import os, sys
rootdir = sys.argv[1]
queue = [rootdir]
while queue:
file = queue.pop(0)
print(file)
if os.path.isdir(file):
queue.extend(os.path.join(file,x) for x in os.listdir(file))
편집하다:
- 사용
os.path
-대신 모듈os.stat
-기능 및stat
-기준 치수. - 사용
list.pop
그리고list.extend
대신에del
그리고+=
운영자.
내 느낌은 이것이 이전에 언급 된 것보다 더 나은 솔루션이라는 것입니다. 여기에는 Grep과 그와 같은 루프가 포함되지만, 특히 완전한 찾기 버퍼가 아닌 라인 버퍼를 원하는 경우 특히 잘 작동합니다.
다음은 더 많은 리소스 집약적입니다.
- 많은 포크
- 많은 발견
- 현재 깊이의 각 디렉토리는 파일 구조에 대한 전체 깊이가있는만큼 여러 번 찾기에 의해 타격을받습니다 (실제로 RAM의 양이 있으면 문제가되지 않아야합니다 ...)
이것은 다음과 같습니다.
- Bash 및 기본 GNU 도구를 사용합니다
- 원할 때마다 깨질 수 있습니다 (비행기를 찾는 것을 보는 것처럼)
- 그것은 줄 당 작동하지 않고 찾을 때마다 작동하므로 후속 명령은 찾기와 종류를 기다릴 필요가 없습니다.
- 실제 파일 시스템 분리를 기반으로 작동하므로 슬래시가있는 디렉토리가 있으면 더 깊이 나열되지 않습니다. 다른 경로 분리기가 구성된 경우에도 여전히 괜찮습니다.
#!/bin/bash depth=0 while find -mindepth $depth -maxdepth $depth | grep '.' do depth=$((depth + 1)) done
당신은 또한 그것을 한 줄에 공정하게 (?) 쉽게 맞출 수 있습니다.
depth=0; while find -mindepth $depth -maxdepth $depth | grep --color=never '.'; do depth=$((depth + 1)); done
그러나 나는 타이핑보다 작은 스크립트를 선호합니다 ...
현재 디렉토리의 디렉토리 예 목록 아래에있는 find 명령, find/path/to/dir -type d를 사용할 수 있습니다.
find . -type d
나는 이것을 할 방법을 찾으려고 노력했다 find
그러나 그것은 a와 같은 것이없는 것 같습니다 -breadth
옵션. 패치를 쓰지 않아서 다음 쉘 주문을 시도하십시오 (배쉬 용) :
LIST="$(find . -mindepth 1 -maxdepth 1 -type d)";
while test -n "$LIST"; do
for F in $LIST; do
echo $F;
test -d "$F" && NLIST="$NLIST $(find $F -maxdepth 1 -mindepth 1 -type d)";
done;
LIST=$NLIST;
NLIST="";
done
나는 우연히 이것을 우연히 발견했기 때문에 그것이 일반적으로 작동하는지 모르겠다 (나는 당신이 묻는 특정 디렉토리 구조에서만 테스트하고 있었다).
깊이를 제한하려면 외부 루프에 카운터 변수를 넣으십시오 (이에 주석도 추가).
# initialize the list of subdirectories being processed
LIST="$(find . -mindepth 1 -maxdepth 1 -type d)";
# initialize the depth counter to 0
let i=0;
# as long as there are more subdirectories to process and we haven't hit the max depth
while test "$i" -lt 2 -a -n "$LIST"; do
# increment the depth counter
let i++;
# for each subdirectory in the current list
for F in $LIST; do
# print it
echo $F;
# double-check that it is indeed a directory, and if so
# append its contents to the list for the next level
test -d "$F" && NLIST="$NLIST $(find $F -maxdepth 1 -mindepth 1 -type d)";
done;
# set the current list equal to the next level's list
LIST=$NLIST;
# clear the next level's list
NLIST="";
done
(2 인치를 교체하십시오 -lt 2
깊이와 함께)
기본적으로 이것은 사용 사용 표준 폭이 먼저 검색 알고리즘을 구현합니다 $LIST
그리고 $NLIST
디렉토리 이름의 대기열로. 다음은 쉬운 카피 앤 페이스트를위한 1 라이너로서의 후자의 접근 방식입니다.
LIST="$(find . -mindepth 1 -maxdepth 1 -type d)"; let i=0; while test "$i" -lt 2 -a -n "$LIST"; do let i++; for F in $LIST; do echo $F; test -d "$F" && NLIST="$NLIST $(find $F -maxdepth 1 -mindepth 1 -type d)"; done; LIST=$NLIST; NLIST=""; done
자격이없는 순서없이 : -maxdepth -type d를 찾으십시오
자격이있는 주문을 얻으려면이 작은 쉘 스크립트와 함께 재귀를 직접 수행해야합니다.
#!/bin/bash
r ()
{
let level=$3+1
if [ $level -gt $4 ]; then return 0; fi
cd "$1"
for d in *; do
if [ -d "$d" ]; then
echo $2/$d
fi;
done
for d in *; do
if [ -d "$d" ]; then
(r "$d" "$2/$d" $level $4)
fi;
done
}
r "$1" "$1" 0 "$2"
그런 다음 매개 변수 기준 디렉토리 및 깊이 로이 스크립트를 호출 할 수 있습니다.
다음은 찾기를 사용하여 가능한 방법입니다. 철저히 테스트하지 않았으므로 사용자는 조심해야합니다 ...
depth=0
output=$(find . -mindepth $depth -maxdepth $depth -type d | sort);
until [[ ${#output} -eq 0 ]]; do
echo "$output"
let depth=$depth+1
output=$(find . -mindepth $depth -maxdepth $depth -type d | sort)
done
이 같은:
find . -type d |
perl -lne'push @_, $_;
print join $/,
sort {
length $a <=> length $b ||
$a cmp $b
} @_ if eof'