$ 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
循环。 - 易于阅读。