다음과 같은 파일 계층 구조가 있습니다.
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'
find
sort
( 파일 경로가 여러 줄로 구성될 수 있으므로 NUL로 구분된 레코드를 사용하지 않는 한 의 출력을 파이프로 연결할 수 없습니다 . -print0
그리고 현재는 일반적이지만(곧 POSIX가 될 예정이지만 덜 일반적인) -z
GNU 확장입니다 .-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
) 및 디렉터리( )를 검색 합니다 .d
depth >= 2
Linux, FreeBSD, OpenBSD, NetBSD, macOS, Solaris 및 Cygwin에서 작동합니다.