find
폴더 내의 특정 파일 패턴을 제외하고 해당 폴더의 하위 폴더는 제외하는 명령을 원합니다 . 예를 들어 제외하려는 경우 subdir1/subdir1.1/UndesiredFiles*.tgz
별표는 폴더 이름 구분 기호를 포함한 연속 문자와 일치하므로 다음은 작동하지 않습니다 /
.
find * -not -path 'subdir1/subdir1.1/UndesiredFiles*.tgz'
위에서는 제외하고 싶지 않은 다음 항목을 제외합니다.
subdir1/subdir1.1/UndesiredFilesAndMore/*.tgz
subdir1/subdir1.1/UndesiredFilesAndMore/StillMore/*.tgz
저는 Gnu find
버전 4.9.0을 사용하고 있습니다.
답변1
일부 find
구현은 쉘 glob 패턴 대신 정규식(구현 및 옵션 또는 기타 조건자에 따라 변형이 다르지만)을 사용한다는 점을 제외하고 -regex
동일한 조건자를 지원합니다. 비표준 BSD 스타일 조건자를 지원한다는 -path
점을 고려하면 아마도 그 중 하나일 것입니다.find
-not
LC_ALL=C find . ! -regex '\./subdir1/subdir1\.1/UndesiredFiles[^/]*\.tgz'
*
glob 연산자(regexp와 동일 .*
: 0개 이상의 문자)를 regexp [^/*]
(0개 이상의 문자 제외 /
) 로 대체 합니다 .
정규식은 기본적으로 고정되어 있으므로 명시적인 ^
또는 가 필요하지 않습니다 $
.
모든 문자와 일치하는 정규식 연산자와 마찬가지로 리터럴만 일치하도록 이스케이프를 .
사용해야 합니다 \.
( [.]
가능하더라도). s는 파일 이름에서 매우 일반적 .
이므로 간과하기 쉽습니다 ..
LC_ALL=C
모든 파일 및 디렉터리 이름이 사용자 로케일의 유효한 문자로만 구성되도록 보장할 수 없는 경우 일반적으로 필수입니다 (이는 -path
btw에도 적용됩니다).
BSD에서는 표준 기본 정규식을 사용하며 -regex
for 또는 와 같은 옵션을 사용하여 표준 확장 정규식으로 변경할 수 있습니다. GNU의 경우 기본적으로 이는 emacs 정규식의 고대 버전이지만 다양한 다른 버전으로 변경될 수 있습니다.-E
grep
sed
find
-regextype
술부. 그럼에도 불구하고 위의 특정 정규식은 어떤 변형에서도 작동합니다.
find
지원되지 않는 의 경우 다음 -regex
을 수행할 수 있습니다.
LC_ALL=C find . ! '(' -path './subdir1/subdir1.1/UndesiredFiles*.tgz' \
! -path './subdir1/subdir1.1/*/*' ')'
즉, 하나 이상의 가 포함된 일치 항목을 ./subdir1/subdir1.1/UndesiredFiles*.tgz
제외하고 필터링합니다 .*
/
또는 다음 perl
을 필터링할 수 있습니다.
find . -exec printf '%s\0' {} + |
perl -l -0ne 'print unless m{^\Q./subdir1/subdir1.1/UndesiredFiles\E[^/]*\.tgz\z}'
여기서는 \Q...\E
내용을 고정 문자열로 처리하여 정규식 연산자를 이스케이프할 필요가 없습니다. 여기에서는 정규식을 ^
시작과 끝 부분에 고정 해야 합니다 ( 정규식은 끝이나 후행 줄 바꿈이 Perl에서 일치하지 않으므로 파일이 "잘못" 제외됩니다 ).\z
$
$'UndesiredFiles.tgz\n'
(경로를 인수로 사용하여 명령을 실행하여 대체 print
됨 system "cmd", $_
)
일부(대부분) find
구현은 -exec printf '%s\0' {} +
로 대체될 수 있습니다 -print0
. 일부 xargs
구현은 -0
또는 옵션을 통해 -d '\0'
이 출력 형식을 지원합니다 .
find . -print0 |
perl -0 -lne 'print unless m{^\Q./subdir1/subdir1\.1/UndesiredFiles\E[^/]*\.tgz\z}' |
xargs -r0 cmd
-l
옵션이 이동됨뒤쪽에 -0
출력 레코드 구분 기호도 NUL입니다.
zsh
쉘을 사용하는 경우에는 이것이 필요하지 않습니다 find
. 다음을 수행할 수 있습니다.
set -o extendedglob
print -rC1 -- **/*~subdir1/subdir1.1/UndesiredFiles[^/]#.tgz(ND)
여기서 #
정규식과 동등한 Extendedglob은 다음 *
과 같습니다.~
와는 별개로/설마and 연산자는 일치하는 전역 확장 동작에 (ND)
적용됩니다 nullglob
(일치하지 않으면 아무것도 확장되지 않음) 및 (숨겨진 파일 포함) . match 의 동작을 더 일치시키기 위해 목록 에 한정자를 추가 할 수도 있습니다 .dotglob
find
oN
N
o
find
print -rC1 --
print
r
s 열이지만 1
C
물론 다른 명령을 사용하거나 목록을 반복할 수도 있습니다 for
.
**/*
(하위 디렉터리 수에 관계없이 모든 이름을 가진 모든 파일과 일치, 축약됨) 이 옵션이 설정되면 (*/)#*
로 축약될 수 있습니다.**
globstarshort
어쨌든, 이들 모두는 제외되지만 ./subdir1/subdir1.1/UndesiredFiles-whatever.tgz
,아니요Exclude ./subdir1/subdir1.1/UndesiredFiles-whatever.tgz/other/file
패턴을 조정하거나 -prune
find
조건자를 사용하여 제외해야 합니다.