YMMV

YMMV

$ sh backup-para-s3.sh

backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator
backup-to-s3.sh: 11: [: bkup_20151106_150532.zip: unexpected operator

ubuntu@accretive-staging-32gb-ephemeral:~$ cat backup-to-s3.sh

#Script to move /home/ubuntu/backup folder  to S3://auto-backup
#Author Ashish Karpe
cd /mnt/backup
filename="bkup_$(date +%Y%m%d_)"
/bin/ls -alF | awk '{ print $9 }'  > /tmp/file

for i in $(cat /tmp/file); do
#       echo $i;
#       read a;
#       echo $filename;
        if [ $filename* = $i ]
        then
                echo "Copying " $i "to S3://auto-backup";
                s3cmd put $i s3://auto-backup

            fi

done

Responder1

  1. não use forpara iterar nas linhas de um arquivo, use

    while IFS= read -r line; do ...; done < filename
    
  2. você não precisa canalizar lsa saída para um arquivo,especialmenteusando-F

  3. use bash [[ x == y ]]para comparações de padrões, e o padrão está no lado direito:
#!/bin/bash
cd /mnt/backup
prefix="bkup_$(date +%Y%m%d_)"

for file in * .*; do
    [[ -f $file ]] || continue    # skip things like directories and soft links
    if [[ $file == $prefix* ]]; then
        echo "Copying " $file "to S3://auto-backup";
        s3cmd put $file s3://auto-backup
    fi
done < /tmp/file

Responder2

Mesmo que você esteja despejando a saída de 'ls' em um arquivo e analisando, você está analisando indiretamente a saída de 'ls', o que é problemático, uma péssima ideia ou ERRADO!!! dependendo de quem você pergunta.

Aqui estápor que você não deve analisar a saída de 'ls'!

Aqui estáNomes de arquivos e caminhos no Shell: como fazer isso corretamente!

Por exemplo, se um dos arquivos tiver um '-' (traço/hífen) no nome do arquivo que não tem escape (prefixando-o com uma barra invertida ('\')), ele pode ser interpretado como um parâmetro.

Evitar a análise de 'ls' pode ser tão simples quanto;

find . -maxdepth 1 -iname "*"
.
./dont_parse_ls.sh
./array.dat
./.bashrc
./BASH.Indirect.Reference.sh
./basharray.sh
./.forever

O que sai igual a

/bin/ls -alF | awk '{ print $9 }'

./
../
.bashrc
.forever/
BASH.Indirect.Reference.sh
array.dat
basharray.sh*
dont_parse_ls.sh

YMMV

Responder3

Existem pelo menos dois problemas principais no script. Seu problema fundamental é o trecho:

if [ $filename* =

Existem alguns problemas com isso. Primeiro, em scripts de shell, você não pode "globar" um padrão de correspondência. Bem, você pode, mas se o fileglob resultar em mais de uma correspondência, você obterá os dois; nesse caso, o programa "[" (sim, é um programa) tentará avaliar:

filename1 filename2 filename3 = $i

Funciona se e somente se o fileglob se expandir para exatamente um nome de arquivo, e você raramente pode garantir isso. No seu caso, $filename se expande para pelo menos um arquivo, mas você deve estar ciente de que nem sempre é esse o caso. Se "$file*" se expandir para nenhum arquivo, você poderá (dependendo da configuração do shopt) obter a string vazia:

= $i

o que fará com que ele [falhe. Com a loja certa, no entanto, você obtém:

backup-2014-whatever* = $i

Com o *ser parte da comparação.

O segundo problema fundamental é o uso do -Fparâmetro em ls. Isso diz ao ls para anexar ao nome do arquivo um dos vários caracteres, dependendo se o arquivo é um executável, um soft-link, etc.

NetScr1be está no caminho certo, mas veja, você não precisa seguir o conselho do NetScr1be e nunca usar ls... apenas não use ls -l. Em vez disso, use ls -1which imprimirá apenas os nomes dos arquivos em uma única coluna, sem frescuras. (Para diretórios muito grandes, ele irá classificá-los, e isso pode ser um problema; nesse caso, há uma opção de não classificação; ou use find.)

Para ser mais seguro, suas variáveis ​​​​devem estar entre aspas duplas e tanto LHS quanto RHS prefixados com um caractere fictício, para garantir que nomes de arquivos estranhos que começam com a -não sejam confundidos.

Eu usaria o conselho de Glenn, mais ou menos, e faria desta forma:

command ls -1 | while read file; do
    if [ x"$file" = x"$filename" ]]; then 
        echo Do Work Here
    fi
done

Foi assim que euseriafazer isso, mas Glenn gentilmente me informou, eu realmente deveria fazer issodelecaminho:

for file in *; do 
    if [[ $file == $filename ]]; then ...

Responder4

Este script faz tudo. Por que não isso? O shell selecionará os arquivos corretos para você, portanto não há necessidade de chamar ls:

#!/bin/sh
for file in /mnt/backup/bkup_$(date +%Y%m%d)_*
do
    s3cmd put "$file" s3://auto-backup
done
  • O único comando externo é s3cmd.
  • Sem ifdeclarações.
  • O único ponto de decisão é o forloop.
  • Fácil de ler.

informação relacionada