[shell] GNU가 공백으로 파일 이름을 처리 할 수 ​​있습니까?

몇 개의 파일이 포함 된 디렉토리가 있으며 일부 파일에는 이름에 공백이 있습니다.

Test workspace/
Another directory/
file1.ext
file2.ext
demo 2012-03-23.odp

$(wildcard)이 디렉토리에서 GNU의 명령을 사용한 다음를 사용하여 결과를 반복하여 $(foreach)모든 것을 인쇄합니다. 코드는 다음과 같습니다.

FOO := $(wildcard *)
$(info FOO = $(FOO))
$(foreach PLACE,$(FOO),$(info PLACE = $(PLACE)))

인쇄 된 내용은 다음과 같습니다.

Test workspace
Another directory
file1.ext
file2.ext
demo 2012-03-23.odp

실제로 얻을 수있는 것은 다음과 같습니다.

Test
workspace
Another
directory
file1.ext
file2.ext
demo
2012-03-23.odp

후자는 분명히 나에게 쓸모가 없습니다. 문서 에 대한 $(wildcard)이 완전히 “이름의 공백으로 구분 된 목록”을 반환하지만 플랫 아웃 상태는 큰 문제가이 인상을 인정하는 데 실패합니다. 도 아니다 않는 문서 를 들어 $(foreach).

이 문제를 해결할 수 있습니까? 그렇다면 어떻게? 공백을 제거하기 위해 모든 파일과 디렉토리의 이름을 바꾸는 것은 옵션이 아닙니다.



답변

버그 # 712 는 make가 공백이있는 이름을 처리하지 않는다고 제안합니다. 어디에도, 결코.

( 오타 또는 형식 지정 아티팩트 인 것처럼 보임) 공백을 이스케이프하여 부분적으로 구현 되었다는 블로그 게시물을 찾았 지만 :\\\

  • 을 제외한 어떤 기능에서도 작동하지 않습니다 $(wildcard).
  • 특별한 변수를 포함하는 변수에서 이름의 목록을 확장 할 때 그것은 작동하지 않습니다 $?, $^그리고 $+뿐만 아니라 사용자 정의 변수를. 즉 $(wildcard), 올바른 파일과 일치 하는 동안 결과를 해석 할 수는 없습니다.

따라서 명시 적이거나 매우 간단한 패턴 규칙을 사용하면 작동하도록 할 수 있지만 그 이상은 운이 없습니다. 공간을 지원하는 다른 빌드 시스템을 찾아야합니다. jam / bjam 이 작동 하는지 , scons , waf , ant , nantmsbuild가 모두 작동 하는지 확실 하지 않습니다 .


답변

GNU Make는 공백으로 구분 된 파일 이름으로 매우 열악합니다.

공백은 모든 곳에서 단어 목록의 구분 기호로 사용됩니다.

이 블로그 게시물 은 상황을 잘 요약하지만 경고 : \가 아닌 \\를 잘못 사용합니다.

target: some\ file some\ other\ file

some\ file some\ other\ file:
    echo done

변수를 사용할 수도 있으므로 이것도 작동합니다.

VAR := some\ file some\ other\ file

target: $(VAR)

$(VAR):
    echo done

wildcard기능 만이 탈출을 인식하므로 많은 고통 없이는 멋진 일을 할 수 없습니다.


그러나 쉘이 구분 기호로도 공백을 사용한다는 것을 잊지 마십시오 .

나는 변경을 원하는 경우 echo donetouch $@, 나는 나의 쉘을 탈출 슬래시를 추가해야 할 것이다.

VAR := some\ file

target: $(VAR)

$(VAR):
    touch $(subst \,\\,$@)

또는 따옴표를 사용하십시오.

VAR := some\ file some\ other\ file

target: $(VAR)

$(VAR):
    touch '$@'

결국 GNU make와 쉘 모두에서 많은 고통을 피하려면 파일 이름에 공백을 넣지 마십시오. 그렇게한다면 Make의 제한된 기능으로 충분할 것입니다.


답변

이 방법을 사용하면 파일 $?목록 인 및 사용자 변수와 같은 나열된 파일 이름을 사용할 수도 있습니다.

Make에서 공백을 처리하는 가장 좋은 방법은 다른 문자를 공백으로 대체하는 것입니다.

s+ = $(subst \ ,+,$1)

+s = $(subst +,\ ,$1)

$(call s+,foo bar): $(call s+,bar baz) $(call s+,bar\ baz2)
    # Will also shows list of dependencies with spaces.  
    @echo Making $(call +s,$@) from $(call +s,$?)

$(call s+,bar\ baz):

    @echo Making $(call +s,$@)

$(call s+,bar\ baz2):

    @echo Making $(call +s,$@)

출력

Making bar baz
Making bar baz2
Making foo bar from bar baz bar baz2

그런 다음 모든 GNU Make 함수를 사용하여 파일 이름 목록을 안전하게 조작 할 수 있습니다. 규칙에서 이러한 이름을 사용하기 전에 +를 제거해야합니다.

SRCS := a\ b.c c\ d.c e\ f.c

SRCS := $(call s+,$(SRCS))

# Can manipulate list with substituted spaces
OBJS := $(SRCS:.c=.o)

# Rule that has object files as dependencies.
exampleRule:$(call +s,$(OBJS))
    # You can now use the list of OBJS (spaces are converted back).
    @echo Object files: $(call +s,$(OBJS))

a\ b.o:
    # a b.o rule commands go here...
    @echo in rule: a b.o

c\ d.o:

e\ f.o:

출력

in rule: a b.o
Object files: a b.o c d.o e f.o

이 정보는 모두 다른 사람이 게시 한 블로그 에서 가져온 것입니다.

대부분의 사람들은 경로에 공백을 사용하지 않거나 Windows 8.3 경로를 사용하는 것을 권장하는 것처럼 보이지만 공백을 사용해야하는 경우 공백을 이스케이프하고 대체가 작동합니다.


답변

쉘에 조금 더 의존하고 싶다면 공백이있는 이름을 저장할 수있는 목록이 제공됩니다.

$(shell find | sed 's: :\\ :g')


답변

원래의 질문은 “이름 바꾸기는 선택 사항이 아닙니다”라고 말했지만 많은 주석가들은 이름 바꾸기가 Make가 공백을 처리 할 수있는 유일한 방법이라고 지적했습니다. 중간 방법을 제안합니다. Make를 사용하여 파일 이름을 임시로 바꾼 다음 다시 이름을 바꿉니다. 이것은 암시 적 규칙과 다른 장점으로 Make의 모든 기능을 제공하지만 파일 이름 지정 체계를 엉망으로 만들지는 않습니다.

# Make cannot handle spaces in filenames, so temporarily rename them
nospaces:
    rename -v 's/ /%20/g' *\ *
# After Make is done, rename files back to having spaces
yesspaces:
    rename -v 's/%20/ /g' *%20*

당신은 손으로이 목표를 부를 수 make nospacesmake yesspaces, 또는 당신이 그들에 따라 다른 목표를 가질 수있다. 예를 들어, 파일을 서버와 다시 동기화하기 전에 파일 이름에 공백을 다시 넣어야하는 “푸시”대상이 필요할 수 있습니다.

# Put spaces back in filenames before uploading
push: yesspaces
    git push

[(!) 참고 : 내가 사용하는 제안 대답 시도 +ss+하지만 내 메이크 열심히 읽고 디버깅하기 위해 만들었다. 묵시적 규칙에 대해 욕을 먹었을 때 포기했습니다 %.wav : %.ogg ; oggdec "$<"..]


답변