특정 하위 디렉터리의 파일을 나열하고 싶지만 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 스크립트 해석과 같은 간단한 작업을 수행하기에는 너무 비대해졌기 때문에 bash
GNU 셸 사용을 중단했습니다 .sh
sh
귀하의 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 이상을 사용하면 printf
NL find
문자로 구분되어 출력됩니다. NL
및 둘 다 SPC
파일 이름에 완전히 유효한 문자이므로 사후 처리 중에 이러한 출력을 신뢰할 수 없습니다. 사용자에게 표시하기에는 적합하지 않지만 후처리에는 사용할 수 있는 를 '%s\0'
대신 사용할 수 있습니다 '%s\n'
(또는 지원되는 경우 를 사용할 수 있습니다 find
) .-print0
효율성 측면에서 Ubuntu 20.04 /bin/sh
(대시 0.5.10.2)와 Ubuntu 20.04 find
(GNU find
4.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는 시스템, 구현, 해당 유틸리티 버전 및 연결된 라이브러리에 따라 다릅니다.
이제 역사상,전반적인 상황이 이름은 실제로 glob
1970년대 초 최초의 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