我在尝试备份此目录中的每个 .qcow2 扩展名时遇到错误。如何以不同的方式备份目录中的所有内容?
这是我的脚本和错误:
#!/bin/bash
for (( i =1; i<5; i++))
do
gzip < /var/lib/libvirt/images/*.qcow2 > /root/bin/backup/full/vm$i.qcow2.backup.gz
done
./assnBackup.bash: line 5: /var/lib/libvirt/images/*.qcow2: ambiguous redirect
./assnBackup.bash: line 5: /var/lib/libvirt/images/*.qcow2: ambiguous redirect
./assnBackup.bash: line 5: /var/lib/libvirt/images/*.qcow2: ambiguous redirect
./assnBackup.bash: line 5: /var/lib/libvirt/images/*.qcow2: ambiguous redirect
foreach 脚本:
#!/bin/bash
i=0
for f in /var/lib/libvirt/images
do
gzip < $f > /root/bin/backup/full/vm$i.qcow2.backup.gz
i=$((i++))
done
使固定:
#!/bin/bash
i=0
file=/var/lib/libvirt/images/*
for f in $file
do
gzip < $f > /root/bin/backup/full/vm$i.qcow2.backup.gz
i=$((i + 1))
done
答案1
好吧,那么。
如果目录中有多个文件,将尝试重定向所有文件gzip < /.../*.qcow2
的输入。gzip
这是不可能的,所以 Bash 会给出错误。如果该模式仅匹配一个文件,则该模式会起作用。
在第二个中,你有for f in /var/lib/libvirt/images
.好吧,for
迭代列出的单词,这里只有一个。它本身不会迭代目录的内容:它也可以用于其他内容,例如for s in foo bar blah ; do echo $s ; done
.因此,您需要明确告诉 shell 使用通配符模式扩展其中的所有文件名。for f in /var/lib/libvirt/images/*.qcow2
将为名称以 结尾的每个文件运行一次循环.qcow2
,并f
保存文件名。
现在,这应该gzip
至少可以工作了。尽管我仍然想知道在进行备份副本时您是否真的想放弃原始文件名。
你可以这样做:
gzip -k "$f" && mv "$f.gz" /root/bin/backup/full/
gzip
默认情况下会创建一个压缩文件,其扩展名.gz
附加在原始文件名上。通常,它也会删除原始文件,但-k
告诉它保留它。然后我们将压缩的副本移走。所以foo.qcow2
会成为foo.qcow2.gz
备份目录中。
不过,如果备份目录位于不同的文件系统上(应该如此),则上述操作确实涉及将压缩文件写入两次。 shell 中的一些字符串操作可以解决这个问题:
gzip "$f" > "/root/bin/backup/full/${f##*/}.gz"
当然,您也可以使用tar
一次归档整个目录,但对于 VM 映像来说,使用起来可能有点尴尬,因为无法随机访问从压缩的 tar 归档中提取单个文件。