
$ 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”可能很簡單;
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
劇本中至少有兩個主要問題。您的根本問題是片段:
if [ $filename* =
這有一些問題。首先,在 shell 腳本中,您不能「通配」匹配模式。好吧,你可以,但是如果 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。)
為了更安全,您的變數應該用雙引號引起來,並且 LHS 和 RHS 都以虛擬字元為前綴,以確保以 a 開頭的奇怪檔案名稱-
不會遺失。
我會或多或少地採納格倫的建議,並這樣做:
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
這個腳本完成了一切。為什麼不是這個? shell 將為您選擇正確的文件,因此無需呼叫ls
:
#!/bin/sh
for file in /mnt/backup/bkup_$(date +%Y%m%d)_*
do
s3cmd put "$file" s3://auto-backup
done
- 唯一的外部命令是
s3cmd
. - 沒有
if
任何聲明。 - 唯一的決策點是
for
循環。 - 易於閱讀。