*쉘의 Glob 파일을 사용하지 않음*

*쉘의 Glob 파일을 사용하지 않음*

특정 하위 디렉터리의 파일을 나열하고 싶지만 docker 컨테이너의 일부로 이 작업을 수행하므로 docker exec실제로 필요하지 않은 셸을 실행하는 데 방해가 되고 싶지 않습니다. 간단한 명령줄 도구(셸뿐만 아니라)를 사용하여 모든 glob 항목을 찾을 수 있습니까?

예를 들어, 현재 호출은 입니다 . 일반적으로 사용되는 도구를 사용하여 더 간단하고 가벼운 bash -l -c 'echo /usr/local/conda-meta/*.json'유사한 것을 생성하는 것이 가능합니까 ?globber /usr/local/conda-meta/*.json

답변1

sh간단하고 보편적으로 사용 가능합니다. sh다양한 언어로 명령줄을 구문 분석하기 위해 호출되는 도구입니다 system(cmdline). 일부 GNU 운영 체제를 포함한 많은 운영 체제는 명령줄 구문 분석 및 POSIX 스크립트 해석과 같은 간단한 작업을 수행하기에는 너무 비대해졌기 때문에 bashGNU 셸 사용을 중단했습니다 .shsh

귀하의 bash -l -c 'echo /usr/local/conda-meta/*.json'명령줄이 해석을 위해 호출되었을 수 있습니다 sh. 어쩌면 이렇게 할 수도 있습니다:

printf '%s\n' /usr/local/conda-meta/*.json

곧장. 그렇지 않은 경우:

sh -c 'printf "%s\n" /usr/local/conda-meta/*.json'

여기서도 find사용할 수 있습니다. find와일드카드를 사용하지 않지만 쉘과 유사한 패턴과 일치하는 파일 이름을 보고할 수 있습니다.

LC_ALL=C find /usr/local/conda-meta/. ! -name . -prune -name '*.json'

또는 일부 find구현을 통해:

LC_ALL=C find /usr/local/conda-meta -mindepth 1 -maxdepth 1 -name '*.json'

( 쉘 구성인 현재 로케일에서 유효한 문자를 형성하는 바이트 시퀀스뿐만 아니라 모든 바이트 시퀀스가 LC_ALL=C​​여기서 일치해야 합니다 *. 쉘이 명령줄을 해석하지 않으면 로 변경해야 할 수도 있습니다 env LC_ALL=C find....)

쉘 글로브와의 몇 가지 차이점:

  • 파일 목록이 정렬되지 않았습니다.
  • 숨겨진 파일 포함(추가 ! -name '.*'하여 제외할 수 있음)
  • 일치하는 파일이 없으면 출력이 제공되지 않습니다. 글로브에는 확장되지 않은 패턴을 그대로 두는 버그 기능이 있습니다.
  • 첫 번째(표준) 변형을 사용하면 파일이 /usr/local/conda-meta/./file.json.
  • 일부 glob은 x*/y/../*z쉽게 번역되지 않습니다(이 경우 디렉터리 심볼릭 링크의 다른 동작에 유의하세요).

그러나 임의의 데이터를 출력하는 데 사용할 수는 없습니다 echo.

내 다음 질문은: 그 출력으로 무엇을 하시겠습니까? 를 사용하면 echo파일 경로가 SPC 문자로 구분되어 출력되고, my 이상을 사용하면 printfNL find문자로 구분되어 출력됩니다. NL및 둘 다 SPC파일 이름에 완전히 유효한 문자이므로 사후 처리 중에 이러한 출력을 신뢰할 수 없습니다. 사용자에게 표시하기에는 적합하지 않지만 후처리에는 사용할 수 있는 를 '%s\0'대신 사용할 수 있습니다 '%s\n'(또는 지원되는 경우 를 사용할 수 있습니다 find) .-print0

효율성 측면에서 Ubuntu 20.04 /bin/sh(대시 0.5.10.2)와 Ubuntu 20.04 find(GNU find4.7.0)를 비교해 보세요.

시작 시간:

$ time (repeat 1000 sh -c '')
( repeat 1000; do; sh -c ''; done; )  0.91s user 0.66s system 105% cpu 1.483 total
$ time (repeat 1000 find . -quit)
( repeat 1000; do; find . -quit; done; )  1.35s user 1.25s system 103% cpu 2.507 total

와일드카드 일부 json파일:

$ TIMEFMT='%U user %S system %P cpu %*E total'
$ time (repeat 1000 sh -c 'printf "%s\n" /usr/share/iso-codes/json/*.json') > /dev/null
0.95s user 0.72s system 105% cpu 1.587 total
$ time (repeat 1000  find /usr/share/iso-codes/json -mindepth 1 -maxdepth 1 -name '*.json') > /dev/null
1.34s user 1.35s system 103% cpu 2.599 total

Even은 여기보다 bash거의 느립니다 .find

$ time (repeat 1000 bash -c 'printf "%s\n" /usr/share/iso-codes/json/*.json') > /dev/null
1.53s user 1.36s system 102% cpu 2.808 total

물론 YMMV는 시스템, 구현, 해당 유틸리티 버전 및 연결된 라이브러리에 따라 다릅니다.

이제 역사상,전반적인 상황이 이름은 실제로 glob1970년대 초 최초의 Unix 버전에서 호출된 유틸리티 이름에서 유래되었습니다. 와일드카드 패턴 확장을 위한 도우미로 /etc찾아 호출 됩니다 .sh

아주 오래된 껍질을 되살리기 위한 일부 프로젝트를 온라인에서 찾을 수 있습니다.https://etsh.nl/. 고고학에 대한 연습으로서 glob다음을 수행할 수 있는 유틸리티를 구축할 수 있습니다.

glob printf '%s\n' '/usr/local/conda-meta/*.json'

하지만 몇 가지 주의 사항이 있습니다.

  • [!x]이것은 지원 되지 않는 고대 구체입니다 [^x].
  • 8비트에서는 안전하지 않습니다. 실제로 비트 8은 다음 용도로 사용됩니다.도망가다glob 연산자( 로 시작하는 파일 이름과 일치하는 것과 $'\xe9*'동일한 내용과 일치합니다 . 쉘은 호출하기 전에 인용 문자에 대해 비트 8을 설정합니다 )i*$'\xaa*'*glob
  • 범위(예: [a-f]데이터 정렬보다는 바이트 값 일치)(실제로 내 생각에는 이것이 종종 장점이 됩니다).
  • 일치하지 않는 글로브는 오류를 일으킬 수 있습니다 No match. (다시 말하지만 아마도 더 좋을 것입니다.부서진1970년대 후반 Bourne 쉘에 의해 개발되었습니다.

glob나중에 1970년대 후반에 PWB 쉘과 Bourne 쉘을 시작으로 이 기능이 쉘로 옮겨졌습니다. 나중에 다른 응용 프로그램에서 해당 기능을 사용할 수 있도록 일부 fnmatch()기능이 glob()C 라이브러리에 추가되었지만 이 기능에 대한 기본 인터페이스인 표준 또는 일반 유틸리티는 알지 못합니다. 초기에도 perl전역 스키마를 확장하기 위해 호출하는 데 사용되었습니다.csh

답변2

전역 파일아니요쉘을 사용하다

읽어야 할 확실한 문서는 다음과 같습니다.글로벌(7).

C 프로그램 호출을 작성하거나 사용할 수 있습니다.경기(3),글로벌(3),인터넷 TV(3),통계(2),디렉터리 읽기(3)

코드를 입력하면장난,파이썬,가다,,오카멜,공통 언어(예를 들어SBCL) ... 비슷한 기능을 찾을 수 있습니다. C++를 사용하여 확인하세요.포코그리고Qt.

나는 당신이 Linux 시스템을 사용하고 있다고 가정합니다. 그런데, 내 대화형 쉘은다루기 힘든(IMHO의 자동 완성 기능이 바람직합니다).

관련 정보