배포용 zip/tarbar를 작성하는 makefile 규칙이 있습니다. 레시피에서는 CR/LF가 올바른지 확인하고 패키징하기 전에 실행 비트가 올바른지 확인하는 등 "부가가치" 작업을 수행합니다.
프로젝트에는 많은 수의 파일이 있지만 요구 사항은 다음과 같습니다: (1) GNUmakefile
need를 제외한 모든 파일 CR/LF
, (3) need만 GNUmakefile
필요 LF
, (3) GNUmakefile
need를 제외한 모든 파일 a-x
.
레시피는 다음과 같습니다.
.PHONY: convert
convert:
chmod a-x *[^GNUmakefile*] TestData/*.dat TestVectors/*.txt
unix2dos --keepdate --quiet *[^GNUmakefile*] TestData/*.dat TestVectors/*.txt
dos2unix --keepdate --quiet GNUmakefile
*
IDE 특정 파일과 같이 일부 파일은 명확하지 않기 때문에 뷔페의 모든 파일을 명시적으로 나열하지 않으려고 노력하고 있습니다 . ( *[^<somefile>*]
이것은 깔끔한 트릭입니다. 저는전역 일치에서 패턴 제외).
문제는 TestData
일치할 TestVectors
때 실행 중이므로 chmod a-x
디렉터리에서 자신을 제외한다는 것입니다.
뭔가를 개선해야 하는데 어떻게 해야 할지 모르겠습니다. 쉘의 "*" glob을 사용하고 싶지만 파일을 제외하고 디렉토리와 일치하지 않습니다.
어떻게 진행해야 하나요?
답변1
filter-out
이 문제는 GNU Make 와 함수를 이용하여 해결하겠습니다 wildcard
. 이들로 수행할 수 없는 유일한 작업 부분은 디렉터리를 필터링하는 것입니다. 이 작업은 셸을 통해 수행되어야 합니다. 아래 코드는 테스트되지 않았으며 (a) 파일 이름에 공백이나 셸 메타 TestData/*.dat
문자 가 없고 (b) TestVectors/*.txt
디렉터리 검사가 필요하지 않다고 가정합니다.
NORM_TOPLEVEL := $(shell for f in $(filter-out GNUMakefile,$(wildcard *)); \
do [ -d "$$f" ] || printf '%s\n' "$$f"; done)
NORM_TESTDIRS := $(wildcard TestData/*.dat) $(wildcard TestVectors/*.txt)
convert:
chmod a-x $(NORM_TOPLEVEL) $(NORM_TESTDIRS)
unix2dos --keepdate --quiet $(NORM_TOPLEVEL) $(NORM_TESTDIRS)
dos2unix --keepdate --quiet GNUmakefile
.PHONY: convert
답변2
glob 만 zsh
유형별로 파일을 선택할 수 있으므로 GNU를 가정하면 make
다음과 같은 것이 필요합니다.
SHELL = zsh
.SHELLFLAGS = -o extendedglob -c
test:
echo ^GNUmakefile(^/)
^GNUmakefile
( extendedglob
) 는 GNUmakefile
.is (^/)
를 제외하고 적용됩니다.글로벌 예선디렉토리 외부의 모든 유형의 파일을 선택하십시오. (.)
파일 형식 도 참조하세요.정기적인(디렉터리 및 fifo, 심볼릭 링크, 소켓과 같은 기타 모든 비 전통적인 유형의 파일 제외...) 이것은 당신이 찾고 있는 것과 더 비슷해 보입니다. 숨겨진( ot) 파일을 포함하려면 D
glob 한정자( )를 추가하세요 (예 : .^GNUmakefile(.D)
D.gitignore
확장은 *[^GNUmakefile*]
, , , , , , , 또는 이외의 문자로 끝나는 숨겨지지 않은 파일 이름의 목록입니다. 따라서 (다음으로 끝나기 때문에) 제외되지만 or도 제외됩니다.G
N
U
m
a
k
e
f
i
l
*
GNUmakefile
e
foo.a
file.html
bar.exe
^GNUmakefile(.)
셸을 변경하지 않고 동일한 작업을 수행하려면 유사한 루프(여기서 동일 ) 를 사용해야 합니다 .
test:
set -- *; \
for i do \
[ -f "$$i" ] && \
[ ! -L "$$i" ] && \
[ "$$i" != GNUmakefile ] && \
set -- "$$@" "$$i"; \
shift; \
done; \
[ "$$#" -gt 0 ] && echo "$$@"
( 숨겨진 파일을 포함 set -- *
하도록 대체됨 set -- .* *
)
find
다음 항목의 가용성을 보장할 수 없는 경우 zsh
가장 좋은 방법은 쉘 글로브에 의지하는 것입니다.
test:
find . ! -name . -prune ! -name '.*' ! -name GNUmakefile \
-type f -exec echo {} +
find TestData/. ! -name . -prune -name '*.dat' ! -name '.*' \
-type f -exec echo {} +
( ! -name '.*'
숨겨진 파일을 포함하기 위해 제거되었습니다).
답변3
더 고급 기준으로 필터링하려는 경우 Python을 사용하여 표현식을 쉽게 확장할 수 있습니다. Python은 거의 모든 곳에 설치됩니다. 이것은 약간 장황하지만 작동합니다.
메이크파일 예:
all:
chmod a-x $(shell python -c "import glob; import os.path; print(' '.join([x for x in glob.glob('TestData/*.dat') + glob.glob('TestVectors/*.txt') if not (os.path.isdir(x) or x == 'GNUmakefile')]))")