¿Cómo agregar argumentos en un bucle ZSH y luego pasarlos a un comando?

¿Cómo agregar argumentos en un bucle ZSH y luego pasarlos a un comando?

Usando mkvmerge, quiero agregar pistas de audio a varios clips MKV organizados así

Clips_folder
/spa/clip1.mka
/spa/clip2.mka
/ger/clip1.mka
/ger/clip2.mka
/clip1.mkv
/clip2.mkv

Ese es el guión que tengo (basado en 'Agregar argumento a la lista de argumentos'):

#!/bin/zsh

mkdir -p output

for video in *.mkv
do
    audioargs=("-o ./output/${video} --language 0:eng ${video}")
    for audiodir in *(/)
        do
            audioargs+=("--language 0:${audiodir} ./${audiodir}/${video:r}.mka")
        done
    echo ${audioargs[@]}
done

Ese es el resultado:

-o ./output/clip1.mkv --language 0:eng clip1.mkv --language 0:spa ./spa/clip1.mka --language 0:ger ./ger/clip1.mka

Pero cuando lo cambio a mkvmerge ${audioargs[@]}me sale

mkvmerge v45.0.0 ('Heaven in Pennies') 64-bit
Error: no destination file name was given

¿Cómo paso correctamente audioargsa mkvmergepara que se expanda a mkvmerge -o file --language ...etc.?

Respuesta1

No tengo mkvmergeque realizar pruebas, pero estoy bastante seguro de que el problema es cómo cita las cosas cuando crea la matriz. Cuando haces algo como

audioargs=("-o ./output/${video} --language 0:eng ${video}")

Las comillas dobles le dicen al shell que trate todo eso como una cadena larga, por lo que se almacena como un solo elemento en la matriz y, por lo tanto, se pasa mkvmergecomo un argumento único que contiene espacios, en lugar de una serie de argumentos.

Nota que echooculta la distinción entre un espacio dentro de un argumento y un espacioentreargumentos, lo que lo hace muy engañoso para cosas como esta. Ponerlo set -xantes del comando debería aclarar lo que realmente está sucediendo. Con sus nombres de archivo de ejemplo, set -xmuestra lo que se está ejecutando:

echo '-o ./output/clip2.mkv --language 0:eng clip2.mkv' '--language 0:ger ./ger/clip2.mka' '--language 0:spa ./spa/clip2.mka'

¿Ves las secciones largas entre comillas simples? Así es como indica que se trata de argumentos largos que contienen espacios, en lugar de secuencias de argumentos separados.

Para resolverlo, simplemente use comillas normales cuando cree la matriz (es decir, las mismas comillas que usaría al pasar argumentos directamente al comando). zsh no divide palabras de forma predeterminada, por lo que técnicamente no es necesario citar ninguna cita, pero prefiero seguir el estilo de citación compatible con otros shells, por lo que cito todas las expansiones variables:

#!/bin/zsh

mkdir -p output

for video in *.mkv
do
    audioargs=(-o "./output/${video}" --language 0:eng "./${video}")
    for audiodir in *(/)
        do
            audioargs+=(--language "0:${audiodir}" "./${audiodir}/${video:r}.mka")
        done
    echo "${audioargs[@]}"
done

Lo que da este resultado con set -x:

echo -o ./output/clip2.mkv --language 0:eng ./clip2.mkv --language 0:ger ./ger/clip2.mka --language 0:spa ./spa/clip2.mka

información relacionada