bash의`[!]`(괄호 안의 느낌표) 와일드 카드


10

나는 글러브 패턴과 와일드 카드를 발견했고 나에게 특히 관심이있다 [!].

이 구문은 [!]대괄호 안의 문자를 일치시키는 것이 아니라를 제외하고 는 구문 과 유사하지만 , [및 사이에 나열되지 않는 한 모든 문자와 일치합니다 ].

rm myfile [!192]

위의 내용은 이름이 192 인 모든 파일을 제외하고 모든 파일을 제거한다고 생각합니다.

그러나 파일 확장명, 특히 여러 조건 으로이 파일을 올바르게 사용하는 것에 대해 걱정하고 있습니다.

그러한 상황에서 올바른 구문은 무엇입니까?

rm myfile [!.gif .csv. mp3] 

또는

rm myfile [!.gif !.csv !.mp3]

내 걱정은 기간이 잘못 될 수도 있으며, 그래서 어떤 A를 파일 .(반드시 왜 그들 중 하나가 될 것입니다)를 조작 할 것이다, 나는 특정 파일의 원인이 조작을 추구하고 때.

이 구문은 [ ]대괄호 안의 문자를 일치시키는 것이 아니라를 제외하고 는 구문 과 유사하지만 , [및 사이에 나열되지 않는 한 모든 문자와 일치합니다 ].

( http://www.tldp.org/LDP/GNU-Linux-Tools-Summary/html/x11655.htm 에서 인용 )

지금; 저에게 단수 !이면 충분하며 그 안의 모든 값은 범위 내에 포함됩니다.


5
일반적인 팁으로, ls my-pattern또는 echo my-command을 사용 하여 글 로빙이 원하는 방식으로 수행되는지 확인하십시오rm
Wayne_Yux

또한 대부분은 아니지만 대부분의 파일에는 확장자가 없습니다. Linux 시스템의 확장은 일반적으로 관련이 없으며 대부분의 프로그램에서 파일 유형을 정의하는 데 사용되지 않습니다.
terdon

2
첫 번째 인용문이 잘못 인용되었습니다. 이제는 기본적으로 [!]비슷하지만 같지 않다고 말합니다.[!]
ilkkachu

2
이 문맥에서 ^와 똑같은 의미 를 가지고 있다는 것을 언급 할 가치가 !있으므로, 다음과 같이 정확하게 [^a]제외 a합니다 [!a]: [다음에 오는 첫 문자가! 또는 ^이면 포함되지 않은 모든 문자가 일치합니다. ( man bash)
디저트

3
rm myfile [!192]제거 할 myfile뿐만 아니라, 단일 문자 파일 이름이없는 1, 9또는 2.
Kevin

답변:


16

인용 man 7 glob:

An  expression  "[!...]"  matches  a single character, namely any character
that is not matched by the expression obtained by removing the first '!' from it.
(Thus, "[!]a-]" matches any single character except ']', 'a' and '-'.)

여기서 단일 문자 부분을 강조하면 []Bash Pattern Matching에서 전체 문자열에 사용할 수 없습니다.


bashBrace Expansion 은 문자열을 일치시키는 데 사용할 수 있지만 문자열을 부정하는 방법은 없습니다. 예 :

1.{gif,csv,mp3}

로 확장

1.gif 1.csv 1.mp3

이러한 파일이 있는지 여부에 관계없이


으로 wchargin 뾰족한 아웃 shopt, 인 그들 중 하나를 확장 패턴 매칭 연산자를 사용 가능하게 할 수있다 !(). 실행 후 shopt -s extglob, 예 :

1.!(gif|csv|mp3)

로 확장

1.jpg 1.bmp 1.png

해당 파일이 현재 디렉토리에 존재하는 경우 자세한 내용은 man bash(확장 / 경로 확장 섹션) 및 경로 확장 (글 로빙) 섹션을 참조하십시오 .


당신이하려는 일을 위해 항상 find다음과 같은 방식으로 부정을 제공하는을 사용 합니다.

find . -maxdepth 1 -type f ! -name "*.gif" -a ! -name "*.csv" -a ! -name "*.mp3"

검색 결과를 제거 하려면 명령 끝에-delete 옵션 추가하면 됩니다. 항상 제거 조치와 마찬가지로 : 항상주의해서 먼저 확인하십시오 .

find에 의해 잘 설명 된 유용한 옵션을 많이 제공합니다 man find.


1
find명령은 재귀 적입니다 ( 편집 : 원래 표시된대로 -추가하지만 관련이없는 정보에 대해서는이 주석을 유지할 수 있습니다). 현재 디렉토리에만 있고 하위 디렉토리가 아닌 파일을 찾아서 -delete조치가 추가 된 경우에만 해당 파일을 삭제하려면 -maxdepth 1바로 뒤에 추가 할 수 있습니다 find .. globstar쉘 옵션이 켜져 있지 않고 사용되지 않는 한 Bash에서 globs가 재귀 적이 지 않기 때문에 globbing 효과와 일치합니다 **. 질문에 표시된 글로브는 모든 쉘에서 비재 귀적입니다.
Eliah Kagan

2
"을 부정 할 수있는 방법은 (내가 아는)이 없다"가진 - shopt -s extglob, 당신이 사용할 수있는 echo 1.!(gif|csv|mp3)모든 인쇄하는 1.extext없는 gif, csv또는 mp3. (의 "패턴 일치"하위 섹션을 참조하십시오 man bash.)
wchargin

10

나는 괄호 사용을 잘못 이해했다고 생각합니다. [abc]일치 문자 a, b또는 c. [!abc]일치 하나 개 입니다 문자 없는 a , b또는 c. 그래서 명령은

rm myfile [192]

제거 myfile와 파일 1, 9그리고 2당신이 myfile을 브래킷 사이에 공간이 있기 때문이다. 대조적으로, 명령

rm myfile[192]

파일을 제거합니다 myfile1, myfile9하고 myfile2.


진실. 사용하는 것이 좋습니다 find.
pLumo

실제로 []는 범위에 사용됩니다. [!] 단일 문자
IronUhlan

1
@IronUhlan은 둘 다 범위 또는 문자 목록을 취합니다. 다른 하나는 부정 일뿐입니다.
ilkkachu

7

대괄호 [ ]는 문자 클래스를 나타냅니다. 그 안에있는 단일 문자는 주어진 위치에서 일치 할 수 있습니다. 그래서

file[192]

세 가지 가능한 이름과 일치합니다.

file1
file2
file9

이후의 단일 문자 만 처리하므로 일치 하지 않습니다 .file192file

대괄호 안에 범위를 사용할 수도 있습니다. [0-9]주어진 위치의 모든 한 자리 숫자와 일치합니다. 두 자리 숫자는을 필요로합니다 [0-9][0-9]. 숫자 다음에 대문자가 나오는 경우 다음을 사용할 수 있습니다 [0-9][A-Z]...

! 부정을 나타냅니다.

file[!192]

또는 또는 file제외 후 단일 문자가있는 파일과 일치합니다 . 예를 들어 and 및 (및 다른 많은)과 일치 하지만 두 개의 추가 문자가 있기 때문에 일치 하지 않습니다 .192file7filesfile% file192

사용 사례의 경우 find대신 대신 사용 하는 것이 좋습니다 [!]. 이것은 보유 not연산자.

또한 재귀 적이므로 기본적으로 모든 하위 디렉토리로 이동합니다. 원하는 경우을 사용하여 현재 디렉토리로 제한 할 수 있습니다 -maxdepth 1. 쉘 와일드 카드 (globbing)는 비재 귀적 **입니다.

심볼릭 링크를 삭제하지 않으려는 -type d경우 디렉토리를 삭제하지 않도록 부정 테스트에 추가 할 수 있습니다 . 그 제안에 대해 Eliah Kagan에게 감사드립니다.

find /path -maxdepth 1 -not \( -type d -or -iname "*.gif" -or -iname "*.csv" -or -iname "*.mp3" \)

원하는 것을 찾으면 다음 명령을 사용하여 명령을 다시 실행할 수 있습니다 -delete

find /path -maxdepth 1  -not \( -type d -or -iname "*.gif" -or -iname "*.csv" -or -iname "*.mp3" \) -delete

2
그리고 한 번에 여러 범위를 수행 할 수도 있다고 생각합니다. 예를 들어, 16 진 숫자는 다음과 같습니다.[0-9a-fA-F]
Wilson

@ 잔나! 사실 :) 찾기를 사용하고 있었다 그것은 "아니"연산자 :)했다 몰랐
IronUhlan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.