Dinamik olarak komut oluşturma


9

Bir komut dosyası üzerinde çalışıyorum ve tarkomutu dinamik olarak oluşturmam gerekiyor .

İşte yapmaya çalıştığım şeyi gösteren iki örnek:

#!/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"

Ben kullanabilmek için istiyorum _tarbunu klasik yolu ile çalışmak yapabilmek oldum bir komut olarak, ama klasörler adına boşluklu işe ihtiyacım var. Ve her seferinde aşağıdaki gibi hatalar aldım:

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

Bilmeniz gereken bir şey var, senaryomun çok eski makinelerde çalışması gerekiyor, yani son bash özelliklerini kullanamıyorum.


--Exclude seçeneğinin yalnızca bundan sonra tek bir dize kabul edebileceğine inanıyorum. Yine de birden fazla --exclude deyiminiz olabilir. Belki "--exclude = / tmp / merhaba --exclude = merhaba" Hata! Boşver. Yanlış anlamışım.
Lewis M

@LewisM Bence OP "/ tmp / merhaba merhaba" dizinini hariç tutmak istiyor (evet, bir boşluk ile.
Archemar

@ShellCode, tüm hariç tutmalardan alıntı yapmaya ne dersiniz, örneğin "--exclude = / tmp / merhaba merhaba"
Archemar

Evet. Bu yüzden Oops ifadesini daha sonra koydum. :)
Lewis M

İnfazın evalönüne geçmeye ne dersiniz ?
jimmij

Yanıtlar:


11

Yürütülebilir bir dize oluşturmaya çalışmayın. Bunun yerine, bir dizide bağımsız değişkenler oluşturun ve bunu çağırırken kullanın tar(zaten bir diziyi doğru şekilde kullanıyorsunuz 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"

İle /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"

Arasında alıntı Not $@içinde shkod ve her ikisinin ${exclude[@]}ve ${exclude_opts[@]}de bashkod. Bu, listelerin ayrı ayrı alıntı yapılan öğelere genişletilmesini sağlar.

İlişkili:


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[@]}"

Cevabı burada genişletiyoruz . Bu herhangi bir bashisms'e dayanmaz, aynı zamanda debian'ın /bin/shve ile de iyi çalışır busybox.


Yardımınız için çok teşekkür ederim, ancak eval'ü gerçekten sevmiyorum, oldukça tehlikeli ... Ayrıca, bu kodu anlamak oldukça zor, daha kolay bir şeyiniz yok mu? : / Komut dosyası dağıtılacak, bu yüzden mümkün olduğunca basit
tutmalıyım

Tehlikeli değil. İle çalıştırın set -x. Tam olarak ne anlamıyorsun?
Mosvy

Ayrıca, stackoverflow'daki orijinal yanıtı okuyun. Bir demo içerir.
Mosvy

Yine de çok iyi çalışıyor ... Kimsenin daha temiz bir cevabı olup olmadığını görmek için bekliyorum, aksi takdirde sizinkini kabul edeceğim. Belki de bu kodda yanlış bir şey yok, ama her bir eval gördüğümde, kodun komut enjeksiyonuna yol açabileceğinden korkuyorum, bu yüzden bundan kaçınmaya çalışıyorum
ShellCode

Cevabı, dizinler> 9 için bir düzeltme ile güncelledim. Gerçekte ne olduğunu görmek için
evalü
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.