대문자만 포함된 파일을 찾으려면 "ls" 명령에 와일드카드 문자를 사용하세요.

대문자만 포함된 파일을 찾으려면 "ls" 명령에 와일드카드 문자를 사용하세요.

그래서 파일 시스템을 조사하다가 /etc이름에 대문자만 있는 파일을 나열할지 고민했습니다. 나는 명령한다

ls *[A-Z]* 

그러나 콘솔에는 하위 문자가 포함된 파일도 표시됩니다. 그냥 ls명령을 사용하고 싶습니다 . 콘솔 프로그램 로케일이 관련이 있습니까?

근본 원인은 무엇입니까?

답변1

[A-Z]대문자를 의미하지는 않습니다. A에서 까지의 문자를 나타내며 Z, 여기에는 소문자도 포함될 수 있습니다. 일반적으로 를 사용해야 합니다 [[:upper:]]. (이것은 Bash 없이도 작동합니다 extglob.)

일치하는 문자는 [A-Z]로케일에 따라 다릅니다.

명확히하다완전히 대문자로 구성된 파일 이름뿐만 아니라 적어도 대문자가 포함된 모든 파일 이름을 어디서나 표시하려고 하지만 를 사용하면 ls *[A-Z]*대문자가 포함되지 않은 일부 파일 이름이 표시됩니다.어느대문자.

이는 로케일의 사전 편찬 순서에 대문자와 소문자(예: AaBbCcDd...)가 섞여 있는 경우에 발생합니다. 다른 로케일(예: LC_ALL=C)을 설정할 수 있지만 일반적으로 가장 좋은 해결 방법은 대문자와 특별히 일치하는 패턴을 작성하는 것입니다.

어떤 문자가 대문자인지로케일마다 다를 수도 있지만 해당 로케일에서 대문자인 경우 이를 포함할 수 있습니다. 그래서 이건 [[:upper:]]단점이라기보다는 장점이 될 수도 있겠네요.

대신 사용하십시오 [[:upper:]].

Bash와 같은 대부분의 Bourne 스타일 쉘은 glob에서 POSIX 문자 클래스를 지원합니다. 이 명령은 /etc이름에 대문자가 하나 이상 포함된 항목을 나열합니다 .

ls -d /etc/*[[:upper:]]*

귀하가 얻는 항목 중 일부는 디렉토리일 수 있습니다. 디렉토리만 나열하는 것이 아니라 해당 내용을 표시하려면 이 -d플래그를 제거하면 됩니다. 로 시작하는 항목이 있는 --경우 패턴 앞에 플래그를 넣을 수도 있습니다 . 하지만 당신은 그것을 모를 수도 있습니다. (스크립트에서는 일반적으로 여기서 이것을 사용하고 싶을 것입니다.)/etc---

파일을 클릭하고 싶지 않을 수도 있지만 클릭한다면...

로 시작하는 항목은 표시되지 않습니다 .. 일반적으로 당신은 그들에게 그것을 보여주고 싶지 않습니다. 정말로 필요한 경우 대부분의 쉘에서는 이와 일치하는 glob을 작성하거나 기본적으로 이를 포함하도록 globbing을 구성할 수 있습니다. .Bash에 선행 항목을 자동으로 포함하는 옵션이 있으며 dotglob를 사용하여 활성화할 수 있습니다 shopt -s dotglob. 다른 쉘에 대해서는 참조 . 아니면 간단히 두 번째 glob을 작성할 수도 있습니다.

ls -d /etc/*[[:upper:]]* /etc/.*[[:upper:]]*

가장 널리 사용되는 Bourne 스타일 쉘은 중괄호 확장을 지원하므로 반복을 줄이고 더 간결하게 작성할 수 있습니다.

ls -d /etc/{,.}*[[:upper:]]*

Bash를 포함한 대부분의 셸에서 두 개의 별도 glob을 작성할 때 그 중 하나가 확장되지 않으면 오류 메시지가 표시됩니다. 왜냐하면 대부분의 셸의 기본 동작은 확장하지 않는 것이기 때문입니다. ls다른 항목과 일치하는 항목은 계속 표시됩니다. 하지만Stéphane Chazelas가 지적했듯이,매우 인기 있는 Zsh를 포함한 일부 셸에서는 전체 명령이 실패하고 ls실행되지 않습니다.명령을 수정하고 다시 실행할 수 있으므로 쉘을 대화식으로 사용하는 경우 실제로 해롭지는 않지만 이 구조는 이식 가능한 스크립트에는 적합하지 않습니다. shell 옵션을 설정하면 Bash도 이 방식으로 실행됩니다 failglob.

이를 위해 와일드카드를 확장할 필요는 없습니다.

Bash에서는 와일드카드 모드에서 POSIX 문자 클래스를 사용하기 위해 확장 와일드카드를 활성화할 필요가 없습니다. 내 Bash 4.3.48 시스템에서:

ek@Io:~$ shopt extglob
extglob         off
ek@Io:~$ ls -d /etc/*[[:upper:]]*
/etc/ConsoleKit     /etc/LatexMk         /etc/ODBCDataSources  /etc/UPower
/etc/ImageMagick-6  /etc/NetworkManager  /etc/rcS.d            /etc/X11

하지만 파일 이름과 일치하려면 필요합니다.오직대문자.

너 뭐야하다다음을 포함하는 파일 이름을 일치시키려면 와일드카드를 확장해야 합니다.오직대문자. 그런 다음 +([[:upper:]])또는 를 사용할 수 있습니다 *([[:upper:]]). 이는 확장된 전역 변수입니다.

Bash를 사용하는 경우 다음을 참조하세요.이 기사,이 가이드,3.5.8.1 패턴 매칭내부에GNU 배쉬 매뉴얼더 알아보기. 당신은 또한 볼 수 있습니다Stefan Chazeras의 답변.

답변2

대문자로만 구성된 파일 이름의 경우.

(예: FOO, ÉTÉ, ΛΈΞΗ; 와 다름 FOO.BAR, ÉTÉ(다음 ÉE악센트 1과 결합된 U+0301))

그리고 ksh또는 zsh -o kshglob -o nobareglobqual또는 bash -O extglob:

ls -d +([[:upper:]])

( 대신 zsh -o extendedglob사용하고 싶은 것 kshglob):

ls -d [[:upper:]]#

또는 GNU를 사용하는 경우 ls(파일 이름에 유효한 문자만 포함되어 있다고 가정):

ls --ignore='*[^[:upper:]]*'

또는 find대신 사용하십시오(여기서는 인수만 출력합니다. 이와 같은 유용한 옵션을 ls사용하고 싶습니다 ).-l

find . ! -name . -prune -name '*' ! -name '*[^[:upper:]]*'

(이것은 -name '*'유효하지 않은 문자가 포함된 파일 이름을 필터링하기 위한 것이며, 다음 문자는 ! -name필터링할 수 없습니다( find적어도 일부 구현에서는))

소문자가 없는 파일 이름의 경우

(그러나 에서와 같이 문자가 아닌 문자는 여전히 허용됩니다 ABC.TXT.) 여기서 ksh:

(FIGNORE='@(.|..|*[[:lower:]]*)'; ls -d -- *)

또는 :bash -O dotglob -O extglobzsh -o kshglob -o dotglob -o nobareglobqual

ls -d -- !(*[[:lower:]]*)

또는 zsh -o extendedglob:

ls -d -- ^*[[:lower:]]*(D)

또는 GNU를 사용하는 경우 ls(파일 이름에 유효한 문자만 포함되어 있다고 가정):

ls -A --ignore='*[[:lower:]]*' --ignore='.*[[:lower:]]*'

(사실 --ignore='.*[[:lower:]]*'뭔가 추가가 필요한 게 제겐 실수인 것 같아요)

그리고 find:

find . ! -name . -prune -name '*' ! -name '*[[:lower:]]*'

(일부 find구현의 경우 유효한 문자가 소문자가 아니더라도 유효하지 않은 문자가 포함된 파일 이름은 포함되지 않습니다.)

하나 이상의 대문자가 포함된 파일 이름의 경우:

( 처럼 보임 Foo.bar, ).Été.txt123.6foo.bar

zsh -o dotglob또는 bash -O dotglob( dotglob이름이 로 시작하는 파일 포함 )을 사용 합니다 ..

ls -d -- *[[:upper:]]*

그리고 find:

find . ! -name . -prune -name '*[[:upper:]]*'

(일부 find구현의 경우 일부 유효한 문자가 대문자이더라도 유효하지 않은 문자가 포함된 파일 이름은 포함되지 않습니다.)


1 문자 결합을 허용하려면 zsh -o pcrematch유니코드 문자 속성을 활용하여 Perl과 유사한 정규식을 사용할 수 있습니다.

ls -d -- *(e@'[[ $REPLY =~ "^(?>\p{Lu}\pM*)*$" ]]'@)

답변3

이전 답변을 용서해주세요. 아직 커피를 마시지 않았습니다.

이 작업을 수행하기 위해 ls를 사용할 수 있는지 잘 모르겠습니다. 그러나 이 문제를 해결할 또 다른 grep은 다음과 같습니다.

LS | egrep ^[^a-z0-9]*$

답변4

왜 ls를 사용하고 싶나요? 대신 find를 사용할 수 있습니다.
find -regex './[A-Z]+'

편집: 다음
을 기반으로 함 man 7 glob:

와일드카드 일치
문자열에 "?", "*" 또는 "[" 문자 중 하나가 포함되어 있으면 와일드카드 패턴입니다. 와일드카드 지정은 와일드카드 패턴을 패턴과 일치하는 경로 이름 목록으로 확장하는 작업입니다. 일치는 다음과 같이 정의됩니다.

ㅏ'? '(대괄호 사이 아님)은 단일 문자와 일치합니다.

'*'(대괄호 사이가 아님)은 빈 문자열을 포함한 모든 문자열과 일치합니다.

캐릭터 클래스

선행 "[" 뒤의 첫 번째 문자가 "!"가 아닌 "[...]" 표현식은 단일 문자, 즉 대괄호로 묶인 모든 문자와 일치합니다.

일반적인 표현
와일드카드 패턴은 다소 비슷하지만 정규식이 아닙니다. 첫째, 텍스트가 아닌 파일 이름과 일치하고 둘째, 규칙이 다릅니다. 예를 들어 정규 표현식의 "*"는 이전 콘텐츠의 복사본이 0개 이상 있음을 의미합니다.

이제 정규 표현식에는 부정이 "^"로 표시되는 대괄호 표현식이 있으므로 POSIX에서는 와일드카드 패턴 "[^...]"의 효과가 정의되지 않는다고 선언했습니다.

ls를 사용하려면 bash가 find -regexp"*"를 or 와 같은 방식으로 번역 하지 않는다는 점을 기억해야 합니다 grep. *[AZ]*는 대문자, 그 뒤에 문자열이 오는 모든 문자열, 즉 기본적으로 모든 문자열을 일치시키려고 시도합니다.

관련 정보