$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 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
答え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'の出力を解析しない理由!
たとえば、ファイル名に "-"(ダッシュ/ハイフン)があり、エスケープされていない場合(前にバックスラッシュ( "\")を追加して)、パラメータとして解釈できます。
「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
青少年MMV
答え3
スクリプトには少なくとも2つの主な問題があります。基本的な問題は彫刻です。
if [ $filename* =
これにはいくつかの問題があります。まず、シェルスクリプトでは、一致するパターンを「ワイルドカード」として指定することはできません。もちろん、これはできますが、fileglobが複数の一致を生成する場合は同時にすべて取得できます。この場合、「[」プログラム(例:プログラム)は次のことを評価しようとします。
filename1 filename2 filename3 = $i
fileglobが正確にファイル名に拡張されている場合にのみ機能しますが、これを保証することはできません。あなたの場合、$ filenameは少なくとも1つのファイルに拡張されますが、必ずしもそうではないことに注意してください。 "$file*" このファイルがまったくないように拡張された場合 (shopt の設定に応じて) 空の文字列を取得できます。
= $i
これにより[
故障が発生します。しかし、正しい店舗を利用すると、次のような利点が得られます。
backup-2014-whatever* = $i
*
比較の一環として。
2番目の基本的な問題は-F
パラメータの使用ですls
。これは、ファイルが実行可能ファイルであるかソフトリンクであるかに応じて、ファイル名に複数の文字のいずれかを追加するようにlsに指示します。
NetScr1beは意味がありますが、NetScr1beのアドバイスに従う必要はなく、絶対に使用しないでくださいls
。ただ使用しないでくださいls -l
。代わりに、ls -1
これを使用すると、ファイル名は装飾なしで単一の列に印刷されます。 (非常に大きなディレクトリの場合はソートするので問題になる可能性があります。この場合はソートされていないオプションがあります。代わりに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
ループです。 - 読みやすい。