find 명령을 사용하여 디렉토리 트리를 재귀적으로 검색하고 지정된 이름과 일치하는 디렉토리에 대한 모든 결과를 반환하려고 합니다.
find . -type d -name '<NAME>'
로그 파일에 인쇄되는 반환된 경로 목록을 얻습니다. 상위 디렉터리에omit.txt라는 파일이 포함된 결과를 무시할 수 있기를 원합니다.
./parent_directory/이름>
나는 이것을 가지고 노력해 왔습니다.
find . -type d -name '<NAME>' \( ! -wholename "*omit.txt*" -prune \)
파일이 포함된 결과를 무시하기 위해 prune 명령을 사용하려고 하는데 이 방법은 디렉터리에만 적용되는 것 같습니다. 어떤 도움이라도 대단히 감사하겠습니다. 단 하나의 명령으로 이 작업을 수행하고 출력 파일을 최대한 유지하려고 합니다.
답변1
find
작업하는 동안 디렉터리 내부의 파일을 볼 수 있어야 하기 때문에 내부에서 이 작업을 정확하게 수행할 수는 없다고 생각합니다 . -prune
디렉터리 자체는 작동되어야 하지만 다른 조건에서는 디렉터리 자체에 내려진 파일 이름 -path
만 볼 수 있습니다 .find
내가 생각할 수 있는 것은 쉘을 분리하여 디렉토리 내부를 살펴보는 것뿐입니다. 이 같은:
$ mkdir -p x y/z ; touch x/foo y/omit.txt
$ find -type d \( -exec sh -c '[ -e "$1/omit.txt" ]' sh {} \; -prune -o -print \)
.
./x
foo -o bar
bar
성공은 평가되지 않으므로 foo
디렉토리가 정리되면 인쇄가 실행되지 않습니다. -o -print
끝에 추가하면 디렉토리 내용도 인쇄할 수 있습니다. exec ... {} +
각 디렉터리에 대한 조건으로 개별적으로 필요하기 때문에 여기서는 사용할 수 없습니다 .
답변2
시스템에서 busybox를 사용할 수 있는 경우 다음을 수행할 수 있습니다.
busybox find . -type d '(' -exec [ -e '{}/omit.txt' ] ';' -prune \
-o -name '<NAME>' -print ')'
busybox는 find
GNU와 마찬가지로 {}
파일 경로까지 확장됩니다.부분이 주장은 이에 의존할 필요를 피 sh
하지만 더 중요한 것은 최신 버전에서는 fork() 또는 execve() 없이 작은 프로그램을 실행할 수 있으므로 대부분의 다른 구현 Magnitude보다 몇 배 더 효율적이라는 [
것입니다 .find
명명된 디렉토리 <NAME>
자체에 a가 포함되어 있을 수 있고 omit.txt
이 경우 이를 인쇄하려는 경우, 아직 잘렸더라도 다음과 같이 변경할 수 있습니다.
busybox find . -type d '(' -exec [ ! -e '{}/omit.txt' ] ';' -o -prune ')' \
-name '<NAME>'
bash가 아닌 bosh 셸에는 find
( like [
)가 내장되어 있으며 -call
해당 조건자를 분기하지 않고도 일부 셸 코드를 실행할 수 있으며 이는 또한 fork() 및 execve()를 절약합니다.
find . -type d '(' -call '[ -e "$1/omit.txt" ]' {} ';' -prune \
-o -name '<NAME>' -print ')'
보다 이식성이 뛰어난 대안은 find
의 File::Find
모듈을 사용하는 것입니다.
perl -MFile::Find -le '
find sub {
if (-e "$_/omit.txt") {
$File::Find::prune = 1;
} else {
print $File::Find::name if ($_ eq "<NAME>") && -d;
}
}, @ARGV' -- .
답변3
@ilkkachu님이 한동안 저를 괴롭혔던 질문에 대한 훌륭한 답변을 주셨네요! 그들에게 꼭 투표하세요. 나는 다른 사람들에게 도움이 될 수 있는 몇 가지 변형을 추가하고 싶었습니다. :)
예제 출력은 다음 구조를 기반으로 합니다.
./
├── a/
│ ├── b/
│ │ └── world.txt
│ └── hello.txt
├── foo.txt
└── some_git_repo/
├── .git/
├── README
└── c/
└── some_git_submodule/
├── .git/
└── README
git repos를 제외한 모든 디렉토리를 인쇄합니다.
find . -type d \( -exec sh -c 'test -e "$1/.git"' sh {} \; -prune -o -print \)
.
./a
./a/b
1. git repos를 포함한 모든 디렉터리를 인쇄합니다.
2. Git 저장소로 재귀하지 마십시오.
find . -type d \( -exec sh -c 'test -e "$1/.git"' sh {} \; -print -prune -o -print \)
.
./a
./a/b
./some_git_repo
git 저장소에 있는 파일을 제외한 모든 파일을 인쇄합니다.
find . \( -exec sh -c 'test -e "$1/.git"' sh {} \; -prune -o -type f -print \)
./foo.txt
./a/b/world.txt
./a/hello.txt
1. git repos에 있는 파일을 제외한 모든 파일을 인쇄합니다.
2. 제외된 git 디렉토리 인쇄
find . \( -exec sh -c 'test -e "$1/.git"' sh {} \; -print -prune -o -type f -print \)
./foo.txt
./a/b/world.txt
./a/hello.txt
./some_git_repo
그러다가 반대...
모든 Git 저장소 인쇄
find . -type d \( -exec sh -c 'test -e "$1/.git"' sh {} \; -print -prune \)
./some_git_repo
하위 모듈을 포함한 모든 git 저장소를 인쇄합니다.
find . -type d \( -exec sh -c 'test -e "$1/.git"' sh {} \; -print \) -o \( -name '.git' -prune \)
./some_git_repo
./some_git_repo/c/some_git_submodule