find 명령에서 최소 깊이를 선택적으로 적용할 수 있나요?

find 명령에서 최소 깊이를 선택적으로 적용할 수 있나요?

다음과 같은 파일 계층 구조가 있습니다.

data
├── debug.log
├── messages
│   ├── msg001.txt
│   ├── msg002.txt
│   └── msg003.txt
└── pictures
    ├── msg002
    │   └── pic001.jpg
    └── msg003
        ├── pic001.jpg
        └── pic002.jpg

처음 두 수준(데이터, 데이터/메시지 및 데이터/그림) 아래의 모든 파일과 모든 디렉터리를 찾고 싶습니다. 계층 구조의 고정된 구조의 일부가 아닌 모든 것(해당되는 경우).

단일 찾기 호출로 이 작업을 수행할 수 있나요?

다음 파일을 찾을 수 있습니다.

$ find data -type f | sort
data/debug.log
data/messages/msg001.txt
data/messages/msg002.txt
data/messages/msg003.txt
data/pictures/msg002/pic001.jpg
data/pictures/msg003/pic001.jpg
data/pictures/msg003/pic002.jpg

디렉토리를 찾을 수 있습니다 :

$ find data -mindepth 2 -type d | sort
data/pictures/msg002
data/pictures/msg003

하지만 -minlength는 테스트가 아니라 옵션이기 때문에 이를 결합할 수 없습니다.

$ find data -type f -o \( -mindepth 2 -type d \) | sort
find: warning: you have specified the -mindepth option after a non-option argument -type, but options are not positional (-mindepth affects tests specified before it as well as those specified after it). Please specify options before other arguments.

data/messages/msg001.txt
data/messages/msg002.txt
data/messages/msg003.txt
data/pictures/msg002
data/pictures/msg002/pic001.jpg
data/pictures/msg003
data/pictures/msg003/pic001.jpg
data/pictures/msg003/pic002.jpg

(data/debug.log는 여기서 찾을 수 없습니다.)

계층 구조의 깊이를 실제 테스트로 고려할 수 있는 방법이 있습니까?

내가 생각할 수 있는 가장 좋은 조합은 경로에서 정규식을 사용하여 디렉터리의 처음 두 수준을 식별하는 것입니다.

$ find data -type f -o \( -type d -regextype posix-extended \! -regex 'data(/[^/]+)?' \) | sort

답변1

계층 구조의 깊이를 실제 테스트로 고려할 수 있는 방법이 있습니까?

에 있습니다FreeBSD 찾기, -depth N조건도 있습니다:

% find data -type f -o -depth +1 -type d |sort
data/debug.log
data/messages/msg001.txt
data/messages/msg002.txt
data/messages/msg003.txt
data/pictures/msg002
data/pictures/msg002/pic001.jpg
data/pictures/msg003
data/pictures/msg003/pic001.jpg
data/pictures/msg003/pic002.jpg

(예, -depth해당 옵션과 혼동되기 쉽습니다.)

"고정 구조"(IMO, 구조가 실제로 고정되었는지 알아야 함)의 일부인 디렉터리 집합을 알고 있는 경우 다음 디렉터리를 제외할 수 있습니다.

% find data ! -path data ! -path data/messages ! -path data/pictures
...

또는 grep과 동일합니다.

% find data | grep -vEe '^(data|data/(pictures|messages))$'
...

find( 대신 기본 출력 형식을 사용했기 때문에 find -print0파일 이름에 개행 문자가 포함되지 않을 수 있습니다)

답변2

이것은 -mindepth비표준 확장입니다(원래는 GNU에서 왔지만 find나중에 다른 구현에 추가됨). 대조적으로 -maxdepth, 표준 술어로 쉽게 시뮬레이션됩니다. 예를 들어 LC_ALL=C find . -path './*/*'GNU 에뮬레이션입니다 find . -mindepth 2.

그래서 여기 있습니다:

LC_ALL=C find data '(' -type d -path '*/*/*' -o -type f ')' -print0 |
  sort -z |
  tr '\0' '\n'

findsort( 파일 경로가 여러 줄로 구성될 수 있으므로 NUL로 구분된 레코드를 사용하지 않는 한 의 출력을 파이프로 연결할 수 없습니다 . -print0그리고 현재는 일반적이지만(곧 POSIX가 될 예정이지만 덜 일반적인) -zGNU 확장입니다 .-print0-z

답변3

가장 좋은 방법은 아니지만 GNU를 사용하여 다음을 수행할 수 있습니다 find.

find data -printf '%d\0%y\0%p\n' | awk -F '\0' '$2 == "f" || $2 == "d" && $1 >= 2 {print $3}'

find-printf플래그를 사용하면 다음 필드가 인쇄됩니다(널 문자 - 로 구분 \0).

  %d     File's depth in the directory tree; 0 means the file is a starting-point.
  %y     File's type (like in ls -l), U=unknown type (shouldn't happen)
  %p     File's name.

그런 다음 명령은 awk깊이가 2( ) 이상인 모든 파일( ) 및 디렉터리의 이름을 인쇄합니다.$2 == "f"$2=="d" && $1 >= 2

답변4

면책 조항: 저는 이 답변에 사용된 생가죽(rh) 프로그램의 현재 작성자입니다(참조https://github.com/raforg/rawhide).

그리고오른쪽 회전, 다음과 같이 할 수 있습니다.

rh data 'f || (d && depth >= 2)'

디렉터리에서 최소 2( ) 깊이의 data파일( f) 및 디렉터리( )를 검색 합니다 .ddepth >= 2

Linux, FreeBSD, OpenBSD, NetBSD, macOS, Solaris 및 Cygwin에서 작동합니다.

관련 정보