백업 파일을 찾고 삭제하는 데 사용하고 있는데 find
특정 디렉터리를 검색에서 제외하고 싶습니다. 백업 파일 이름은 , .bck
또는 으로 끝날 수 있습니다 .bak
~
backup
세 개의 디렉터리만 제외하면 되는 최소 작업 예제(MWE) 코드는 다음과 같습니다.
#! /bin/bash
find . -type d \( -path "./.*" -o -path "./Music" -o -path "./Documents" \) -prune -o -type f \( -name "*.bck" -o -name "*.bak" -o -name "*~" -o -name "*.backup" \) -print0 | xargs -0 --no-run-if-empty trash-put
\( -path "dir1" -o -path "dir2" ... -o -path "dirN" \) -prune
MWE에서는 3개만 표시했지만 제외할 디렉터리가 10개 정도 있는 경우 구문이 약간 투박해 보입니다.
서비스에 푸시할 수 있는 입력 파일(제외된 디렉터리 목록 포함)이나 배열 또는 목록과 같은 구성을 사용하는 더 우아한 방법이 있습니까?
원래 질문을 작성할 때 더 명확하지 않아서 죄송합니다.
참고: trash-put
파일을 삭제하는 대신 파일을 이동하는 Trashcan
유틸리티 입니다[1].
답변1
사용 -path ... -prune
(-o
또는) 괄호로 그룹화된 논리\( ... \)
find /somepath \( -path /a -prune -o \
-path /b -prune -o \
-path /c -prune \
\) \
-o -print
이 예제는 /somepath/a
디렉터리나 파일을 반복하지 않습니다./somepath/b
/somepath/c
이것은 여러 표현식과 복잡한 연산을 사용하여 고안된 예입니다 -exec
. 이는 Linux 호스트의 순수 파일에 대한 파일 경로와 체크섬을 인쇄하고 주로 임시 파일이나 문자 장치가 포함된 경로를 잘라냅니다.
$ find / \( -path /dev -prune -o \
-path /proc -prune -o \
-path /sys -prune \
\) \
-o -type f \
-printf '%p ' -exec sh -c 'md5sum -- "{}" | cut -f1 -d" "' \;
/etc/services 00060e37207f950bf0ebfd25810c19b9
/etc/lsb-release f317530ede1f20079f73063065c1684e
/etc/protocols bb9c019d6524e913fd72441d58b68216
/etc/rsyslog.conf 8f03326e3d7284ef50ac6777ef8a4fb8
...
답변2
GNU find를 사용하면(즉, 내장되지 않은 Linux 또는 Cygwin에서) -regex
이러한 모든 -path
와일드카드를 단일 정규식으로 결합할 수 있습니다.
find . -regextype posix-extended \
-type d -regex '\./(\..*|Music|Documents)' -prune -o \
-type f -regex '.*(\.(bck|bak|backup)|~)' -print0 |
xargs -0 --no-run-if-empty trash-put
BSD 또는 macOS -E
에서는 -regextype posix-extended
.
또한 이를 더 짧은 표준어로 대체할 수도 있습니다 -print0 | xargs -0 --no-run-if-empty trash-put
.--no-run-if-empty
-exec trash-put {} +
1 그러나 더 짧은 -r
형식은 일부 다른 구현에서 지원되며 일부 BSD에서는 기본 구현이기도 합니다.
답변3
find
내가 아는 한, 파일에서 패턴을 읽으라고 지시하는 옵션은 없습니다 . 간단한 해결 방법은 제외하려는 패턴을 파일에 저장하고 해당 파일을 reverse 의 입력으로 전달하는 것입니다 grep
. 예를 들어 다음과 같은 파일과 디렉터리를 만들었습니다.
$ tree -a
.
├── a
├── .aa
├── .aa.bak
├── a.bck
├── b
├── .dir1
│ └── bb1.bak
├── dir2
│ └── bb2.bak
├── b.bak
├── c
├── c~
├── Documents
│ └── Documents.bak
├── exclude.txt
├── foo.backup
└── Music
└── Music.bak
게시한 예를 올바르게 이해했다면 , , 및 휴지통 으로 이동 a.bck
하고 , 및 해당 위치에 보관 하기 를 원할 것입니다. 그래서 다음 내용으로 파일을 만들었습니다 (원하는 만큼 추가할 수 있습니다)..aa.bak
b.bak
c~
foo.backup
dir2/bb2.bak
.aa.bak
.dir1/bb1.bak
Documents/Documents.bak
Music/Music.bak
exclude.txt
$ cat exclude.txt
./.*/
./Music
./Documents
귀하의 초기 결과가 현재 디렉터리( )의 숨겨진 백업 파일을 이동하고 숨겨진 디렉터리( )의 모든 백업 파일을 제외 ./.*/
하려는 의미라는 것을 이해했기 때문에 사용합니다 . 이제 명령을 실행하고 이를 사용하여 원치 않는 파일을 제외할 수 있습니다..foo
.foo/bar
find
grep
$ find . -type f | grep -vZf exclude.txt | xargs -0 --no-run-if-empty trash-put
그렙 옵션:
-v, --invert-match
Invert the sense of matching, to select non-matching
lines. (-v is specified by POSIX.)
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty
file contains zero patterns, and therefore matches
nothing. (-f is specified by POSIX.)
-Z, --null
Output a zero byte (the ASCII NUL character) instead of
the character that normally follows a file name. For
example, grep -lZ outputs a zero byte after each file
name instead of the usual newline. This option makes
the output unambiguous, even in the presence of file
names containing unusual characters like newlines.
This option can be used with commands like find
-print0, perl -0, sort -z, and xargs -0 to process
arbitrary file names, even those that contain newline
characters.
답변4
이것은 문제라기보다는 쉘 문제처럼 보입니다 find
. ("\" 없음!)을 포함하는 파일의 경우 ( -name dir1 -o -name dir2 ) -prune
간단히 다음을 수행할 수 있습니다.
find ... $(< /path/to/file)
그러나 이는 찾기 호출 자체를 변경하지 않고($IFS를 변경하거나 변경하여) eval find
공백이 없는 경로에만 작동합니다 .
파일을 더 간단하게 만들고 싶다면 스크립트를 작성할 수 있습니다.
# file content
dir1
dir2
dir3
# script content
#!/bin/bash
file=/path/to/file
# file may be checked for whitespace here
grep '[^[:space:]]' "$file" | { empty=yes
while read dir; do
if [ yes = "$empty" ]; then
echo -n "( "
empty=no
else
echo -n " -o "
fi
echo -n "-name ${dir}"
done
if [ no = "$empty" ]; then
echo -n " ) -prune"
fi; }
그리고 사용
find ... $(/path/to/script)
대신에.