find
백업 파일을 찾아 삭제 하는 데 사용 하고 있지만 검색에서 특정 디렉토리를 제외하고 싶습니다. 백업 파일 이름에 종료 할 수있는 .bck
, bak
, ~
, 또는 backup
.
제외 할 디렉토리가 세 개 뿐인 MWE (Minimum Working Example) 코드는 다음과 같습니다.
#! /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 개 정도 인 경우에는 문법 이 약간 어수선 해 보입니다.
제외 된 디렉토리 목록이있는 입력 파일 또는 서비스로 압축 될 수있는 배열 또는 목록과 유사한 구성을 사용하는보다 우아한 방법이 있습니까?
원래 질문을 작성할 때 더 명확하게 표시하지 않아서 죄송합니다.
NB : trash-put
파일을 Trashcan
삭제 하는 대신 파일을 옮기는 유틸리티입니다 [1].
답변
내가 아는 find
한 파일에서 패턴을 읽 도록 지시하는 옵션은 없습니다 . 쉬운 해결 방법은 파일에서 제외하려는 패턴을 저장하고 해당 파일을 반전 입력으로 전달하는 것 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.
답변
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
FreeBSD 또는 OSX에서는 -E
대신 사용하십시오 -regextype posix-extended
.
답변
그룹 -path ... -prune
한 표현에 의해 밀폐 \( ... \)
사용 -o
( 또는 ) 논리를.
find /somepath \( -path /a -prune -o \
-path /b -prune -o \
-path /c -prune \
\) \
-o -print
예 것으로 반복하지 디렉토리 또는 또는 아래 파일 /somepath/a
, /somepath/b
및 /somepath/c
.
다음은 여러 작업을 사용하는보다 구체적인 예입니다.
find / \( -path /dev -prune -o \
-path /proc -prune -o \
-path /sys -prune \
\) \
-o -printf '%p ' -exec cksum {} \;
답변
이것은 질문보다 더 중요한 질문 인 것 같습니다 find
. ( -name dir1 -o -name dir2 ) -prune
“\”가없는 파일을 사용하면 다음과 같이 간단하게 수행 할 수 있습니다.
find ... $(< /path/to/file)
찾기 호출 자체를 변경하지 않고 ( eval find
$ IFS를 변경하거나 변경 하여 ) 공백없이 만 경로를 사용할 수 있습니다.
파일을 더 단순하게 유지하려면 스크립트를 작성할 수 있습니다.
# 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)
대신에.