Tengo un directorio que contiene varios archivos, algunos de los cuales tienen espacios en sus nombres:

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

Yo uso GNU $(wildcard) comando en este directorio, y luego iterar sobre el resultado del uso de $(foreach), impresión de todo lo que fuera. Aquí está el código:

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

Aquí es lo que yo esperaría a ver impreso:

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

Aquí es lo que realmente conseguir:

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

El último es obviamente de ninguna utilidad para mí. El documentación para $(wildcard) de plano los estados que devuelve una «lista separada por espacios de nombres», pero es totalmente incapaz de reconocer los enormes problemas que esto conlleva. Tampoco el documentación para $(foreach).

Es posible evitar esto? Si es así, ¿cómo? Cambiar el nombre de cada archivo y directorio para quitar los espacios no es una opción.

InformationsquelleAutor qntm | 2012-03-23

5 Comentarios

  1. 49

    El error #712 sugieren que el no manejar con espacios en el nombre. Nada, nunca.

    He encontrado una blog post diciendo que es parcialmente implementado por escapar de los espacios con \ (\\ parece ser un error de escritura o de formato artefacto), pero:

    • No funciona en ninguna de las funciones excepto $(wildcard).
    • No funciona cuando la expansión de las listas de los nombres de las variables, que incluye las variables especiales $?, $^ y $+ así como cualquier variable definida por el usuario. Que a su vez significa que mientras $(wildcard) coincidirá con archivos correctos, usted no será capaz de interpretar el resultado de todos modos.

    De modo explícito o patrón muy simple reglas puede llegar a trabajar, pero más allá de que usted está fuera de suerte. Usted tendrá que buscar algún otro sistema de construcción que no admite espacios. No estoy seguro de si jam/bjam hace, scons, waf, ant, nant y msbuild todo debería de funcionar.

    • Yo era capaz de conseguir $? y [email protected]. Si usted está interesado, véase mi respuesta a continuación. y Louis, que está mal, que hace el trabajo. Siéntase libre de probar por ti mismo
  2. 19

    GNU Make hace muy poco con espacio separado los nombres de archivo.

    Se utilizan espacios como delimitadores en la lista de palabras por todo el lugar.

    Este blog resume bien la situación, pero ADVERTENCIA: se utiliza incorrectamente \\ en lugar de \

    target: some\ file some\ other\ file
    
    some\ file some\ other\ file:
        echo done

    También puede utilizar variables, por lo que este sería también el trabajo

    VAR := some\ file some\ other\ file
    
    target: $(VAR)
    
    $(VAR):
        echo done

    Sólo el wildcard función reconoce el escape, por lo que no puede hacer nada apetece sin un montón de dolor.


    Pero no olvides que tu shell utiliza espacios como delimitadores demasiado.

    Si yo quería cambiar el echo done a touch [email protected], tendría que agregar barra de escapar de mi concha.

    VAR := some\ file
    
    target: $(VAR)
    
    $(VAR):
        touch $(subst \,\,[email protected])

    o, más probablemente, el uso de comillas

    VAR := some\ file some\ other\ file
    
    target: $(VAR)
    
    $(VAR):
        touch '[email protected]'

    Al final, si se desea evitar un montón de dolor, tanto en GNU make, y en su concha, no poner espacios en sus nombres de archivo. Si lo hace, esperemos que las capacidades limitadas de Hacer será suficiente.

    • «no poner espacios en sus nombres de archivo»: nunca voy a hacer. Pero a veces usted tiene que escribir un archivo que funciona con alguien del código fuente ….
    • Yo entiendo. Acaba de estar preparado para el dolor.
    • No es broma, Pablo. Creo que me pasé un par de horas probando diferentes cosas. Yo estaba tratando de probar una versión por la existencia de un fichero. Me di por vencido. Todo el mundo tiene que usar la misma versión ahora. (Que no es tan difícil en mi caso, pero es una solución poco elegante.)
    • Que puede todavía uso $(shell ...) para hacer iniciales manipulaciones, por suerte.
    • Estoy utilizando el servicio de ENVÍO, así que tengo todas las herramientas de linux en Windows…. y todos mis archivos binarios se encuentran en «Archivos de Programa». Daaaang.
  3. 13

    Este método también permite el uso de la lista de nombres de archivo, tales como $? y las variables de usuario que son listas de archivos.

    La mejor manera de lidiar con espacios en Hacer es sustituir los espacios por otros personajes.

    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,[email protected]) from $(call +s,$?)
    
    $(call s+,bar\ baz):
    
        @echo Making $(call +s,[email protected])
    
    $(call s+,bar\ baz2):
    
        @echo Making $(call +s,[email protected])

    Salidas

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

    Usted puede, a continuación, de forma segura de manipular las listas de los nombres de archivo utilizando todo el Make de GNU
    funciones. Sólo asegúrese de quitar el +’s antes de usar estos nombres en una regla.

    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:

    Salidas

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

    Esta info es todo desde el blog que todo el mundo estaba publicando.

    La mayoría de las personas parecen estar recomendando no usar espacios en las rutas de acceso o el uso de Windows 8.3 caminos, pero si debe usar espacios, escapando de los espacios y la sustitución de las obras.

    • ¿Qué pasa si usted de repente tiene un nombre de archivo con un + en ella?
    • Usted tendría que usar caracteres poco comunes a los nombres de archivo tal vez decir $$$$ o ++++
  4. 4

    Si usted está dispuesto a confiar en su caparazón un poco más, esto le da una lista que puede contener nombres con espacios muy bien:

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

    A la pregunta original, dijo que «el cambio de nombre no es una opción», sin embargo, muchos comentaristas han señalado que el cambio de nombre es casi la única manera de Hacer que puede manejar espacios. Sugiero un camino medio: Uso que se hace para cambiar temporalmente el nombre de los archivos y, a continuación, cambiar el nombre de ellos de nuevo. Esto le da todo el poder de Hacer con reglas implícitas y otras bondad, pero no estropear su esquema de nomenclatura de archivos.

    # 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*

    Puede llamar a estos objetivos mediante la mano con make nospaces y make yesspaces, o usted puede tener otros objetivos depende de ellos. Por ejemplo, usted podría querer tener un «empuje» target, lo que permite asegurarse de poner los espacios en los nombres de archivo antes de la sincronización de archivos con un servidor:

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

    [Nota al margen: yo probé la respuesta que sugiere el uso de +s y s+ pero a mi Makefile más difícil de leer y depurar. Me dio cuando me dio disparates sobre reglas implícitas le gusta: %.wav : %.ogg ; oggdec "$<".]

Dejar respuesta

Please enter your comment!
Please enter your name here