YMMV

YMMV

$ sh резервное копирование-в-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 резервное копирование-в-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

решение1

  1. не используйте forдля перебора строк файла, используйте

    while IFS= read -r line; do ...; done < filename
    
  2. вам вообще не нужно направлять lsвывод в файл,особеннос использованием-F

  3. используйте bash [[ x == y ]]для сравнения шаблонов, шаблон находится справа:
#!/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

решение2

Даже если вы записываете вывод «ls» в файл и анализируете его, вы косвенно анализируете вывод «ls», что либо проблематично, либо является очень плохой идеей, либо НЕПРАВИЛЬНО!!!, в зависимости от того, кого вы спрашиваете.

Вотпочему не следует анализировать вывод 'ls'!

ВотИмена файлов и пути в Shell: как это сделать правильно!

Например, если в имени одного из файлов есть символ «-» (тире/дефис), который не экранирован (путем добавления к нему обратной косой черты ('\')), то он может быть интерпретирован как параметр.

Избежать разбора «ls» можно так же просто:

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

Что получается то же самое, что и

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

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

YMMV

решение3

В сценарии есть как минимум 2 основные проблемы. Ваша основная проблема — это фрагмент:

if [ $filename* =

С этим есть несколько проблем. Во-первых, в скриптах оболочки вы не можете "glob" шаблон соответствия. Ну, вы можете, но если fileglob даст более одного соответствия, вы получите оба, и в этом случае программа "[" (да, это программа) попытается оценить:

filename1 filename2 filename3 = $i

Это работает только в том случае, если fileglob расширяется ровно до одного имени файла, а гарантировать это можно редко. В вашем случае $filename расширяется по крайней мере до одного файла, но вы должны знать, что это не всегда так. Если "$file*" расширяется вообще ни до какого файла, вы можете (в зависимости от настройки shopt) получить пустую строку:

= $i

что приведет [к сбою. Однако при правильном выборе магазина вы вместо этого получите:

backup-2014-whatever* = $i

С *бытием частью сравнения.

Вторая фундаментальная проблема — использование параметра -Fв ls. Это говорит ls о необходимости добавлять к имени файла один из нескольких символов в зависимости от того, является ли файл исполняемым, программной ссылкой и т. д.

NetScr1be в чем-то прав, но, послушайте, вам не обязательно следовать совету NetScr1be и никогда не использовать ls... просто не используйте ls -l. Вместо этого используйте , ls -1который выведет только имена файлов в один столбец, без излишеств. (Для очень больших каталогов он отсортирует их, и это может быть проблемой, в этом случае есть опция без сортировки; или используйте find.)

Для большей безопасности переменные следует заключать в двойные кавычки, а перед левой и правой частью следует ставить фиктивный символ, чтобы не допустить сбоя при использовании странных имен файлов, начинающихся с -.

Я бы воспользовался советом Гленна, в большей или меньшей степени, и сделал бы это следующим образом:

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

Вот как ябысделать это, но Гленн любезно сообщил мне, что мне действительно следует это сделатьегоспособ:

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

решение4

Этот скрипт делает все. Почему бы не сделать это? Оболочка выберет нужные файлы за вас, поэтому нет необходимости вызывать ls:

#!/bin/sh
for file in /mnt/backup/bkup_$(date +%Y%m%d)_*
do
    s3cmd put "$file" s3://auto-backup
done
  • Единственная внешняя команда — s3cmd.
  • Никаких ifзаявлений.
  • Единственная точка принятия решения — это forпетля.
  • Легко читается.

Связанный контент