
$ 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 バックアップ-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
答え1
for
ファイルの行を反復処理するには使用しないでください。while IFS= read -r line; do ...; done < filename
ls
出力をファイルにパイプする必要はまったくありません。特に使用して-F
- パターンの比較には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' の解析を回避するのは次のように簡単です。
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
人によって違う
答え3
スクリプトには少なくとも 2 つの大きな問題があります。根本的な問題はスニペットにあります:
if [ $filename* =
これにはいくつか問題があります。まず、シェル スクリプトでは、一致パターンを「グロブ」できません。まあ、できますが、ファイルグロブの結果が複数の一致になる場合は、両方が取得されます。その場合、「[」プログラム (はい、プログラムです) は、次の評価を試みます。
filename1 filename2 filename3 = $i
これは、ファイルグロブが正確に 1 つのファイル名に展開される場合にのみ機能しますが、それが保証されることはほとんどありません。この場合、$filename は少なくとも 1 つのファイルに展開されますが、常にそうであるとは限らないことに注意してください。"$file*" がまったくファイルに展開されない場合は、(shopt の設定に応じて) 空の文字列が返される可能性があります。
= $i
これにより、が[
失敗します。ただし、適切なショップを使用すると、代わりに次のようになります。
backup-2014-whatever* = $i
*
比較の一部となります。
-F
2 番目の基本的な問題は、 のパラメータの使用ですls
。これは、ファイルが実行可能ファイル、ソフトリンクなどであるかどうかに応じて、ファイル名に複数の文字のうちの 1 つを追加するように ls に指示します。
NetScr1be は良い考えを持っていますが、NetScr1be のアドバイスに従ってls
... を決して使用しなくてもかまいません。 を使用しないでくださいls -l
。 代わりに、ls -1
which を使用すると、ファイル名のみが 1 列に印刷され、余計な機能はありません。 (非常に大きなディレクトリの場合、これはそれらをソートしますが、これが問題になる場合があります。その場合は、no-sort オプションがあります。または find を使用してください。)
-
より安全にするために、変数は二重引用符で囲み、LHS と RHS の両方にダミー文字をプレフィックスとして付けて、a で始まる奇妙なファイル名によって混乱しないようにする必要があります。
私は、Glenn のアドバイスを多かれ少なかれ利用して、次のようにします。
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
ループです。 - 読みやすい。