Crea un comando in modo dinamico


9

Sto lavorando a uno script e devo creare il tarcomando in modo dinamico.

Ecco due esempi per illustrare cosa sto cercando di fare:

#!/bin/bash

TAR_ME="/tmp"

EXCLUDE=("/tmp/hello hello" "/tmp/systemd*" "/tmp/Temp*")
_tar="tar "`printf -- '--exclude="%s" ' "${EXCLUDE[@]}"`" -zcf tmp.tar.gz"
echo COMMAND: "${_tar}"
${_tar} "$TAR_ME"

echo -e "\n\nNEXT:\n\n"

EXCLUDE=("--exclude=/tmp/hello\ hello" "--exclude=/tmp/systemd*" "--exclude=/tmp/Temp*")
_tar="tar "`printf -- '%s ' "${EXCLUDE[@]}"`" -zcf test.tar.gz"
echo COMMAND: "${_tar}"
${_tar} "$TAR_ME"

Voglio essere in grado di utilizzare _tarcome comando, sono stato in grado di farlo funzionare con il percorso classico, ma ne ho bisogno per lavorare con spazi nel nome delle cartelle. E ogni volta ho ricevuto errori che assomigliano a:

COMMAND: tar --exclude="/tmp/hello hello" --exclude="/tmp/systemd*" --exclude="/tmp/Temp*"  -zcf tmp.tar.gz /tmp
tar: hello": Cannot stat: No such file or directory

COMMAND: tar --exclude=/tmp/hello\ hello --exclude=/tmp/systemd* --exclude=/tmp/Temp*  -zcf test.tar.gz 
tar: hello: Cannot stat: No such file or directory

Solo una cosa che devi sapere, ho bisogno che il mio script funzioni su macchine molto vecchie, il che significa che non posso usare le ultime funzionalità di bash.


Credo che l'opzione --exclude possa accettare una sola stringa dopo di essa. Tuttavia, puoi avere più istruzioni --exclude. Forse prova "--exclude = / tmp / hello --exclude = hello" Oops. Non importa. Ho frainteso.
Lewis M,

@LewisM Penso che OP voglia escludere la directory "/ tmp / ciao ciao" (sì, con uno spazio.
Archemar,

@ShellCode per quanto riguarda la citazione di tutto escludi, ad es. "--Exclude = / tmp / hello hello"
Archemar

Si. Ecco perché ho inserito la dichiarazione Oops più tardi. :)
Lewis M,

Che ne dici di metterti evaldi fronte all'esecuzione?
Jimmij,

Risposte:


11

Non provare a creare una stringa eseguibile. Costruisci invece gli argomenti in un array e usalo quando chiami tar(stai già usando un array correttamente per EXCLUDE):

#!/bin/bash

directory=/tmp

exclude=( "hello hello" "systemd*" "Temp*" )

# Now build the list of "--exclude" options from the exclude array:
for elem in "${exclude[@]}"; do
    exclude_opts+=( --exclude="$directory/$elem" )
done

# Run tar
tar -cz -f tmp.tar.gz "${exclude_opts[@]}" "$directory"

Con /bin/sh:

#!/bin/sh

directory=/tmp

set -- "hello hello" "systemd*" "Temp*"

# Now build the list of "--exclude" options from the $@ array
# (overwriting the values in $@ while doing so)
for elem do
    set -- "$@" --exclude="$directory/$elem"
    shift
done

# Run tar
tar -cz -f tmp.tar.gz "$@" "$directory"

Nota la citazione di $@nel shcodice e di entrambi ${exclude[@]}e ${exclude_opts[@]}nel bashcodice. Ciò garantisce che gli elenchi vengano espansi in elementi quotati singolarmente.

Relazionato:


2
mix(){
        p=$1; shift; q=$1; shift; c=
        i=1; for a; do c="$c $q \"\${$i}\""; i=$((i+1)); done
        eval "${p%\%*}$c${p#*\%}"
}
mix 'tar % -zcf tmp.tar.gz' --exclude "/tmp/hello hello" "/tmp/systemd*" "/tmp/Temp*"

EXCLUDE=("/tmp/hello hello" "/tmp/systemd*" "/tmp/Temp*")
mix 'tar % -zcf tmp.tar.gz' --exclude "${EXCLUDE[@]}"

Estendere la risposta qui . Questo non si basa su alcun bashismo, funzionerà bene anche con Debian /bin/she con busybox.


Grazie mille per il tuo aiuto, ma non mi piace molto l'eval, è abbastanza pericoloso ... Inoltre, questo codice è abbastanza difficile da capire, non hai qualcosa di più facile? : / Lo script verrà distribuito, quindi devo mantenerlo il più semplice possibile ...
ShellCode

Non è pericoloso Eseguilo con set -x. Cosa non capisci esattamente?
mosvy,

Inoltre, leggi la risposta originale su StackOverflow. Include una demo.
mosvy

Funziona abbastanza bene però ... In attesa di vedere se qualcuno ha una risposta più pulita, altrimenti accetterò la tua. Forse non c'è niente di sbagliato in quel codice, ma ogni volta che vedo un errore, temo che il codice possa portare all'iniezione di comandi, ecco perché provo ad evitarlo
ShellCode

Ho aggiornato la risposta con una correzione per gli indici> 9. Puoi sostituire l'Eval con un'eco per vedere cosa sta effettivamente ottenendo (l'Eval non vede i nomi dei file)
mosvy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.