![bash 脚本中的 rm 命令不适用于变量](https://linux22.com/image/99724/bash%20%E8%84%9A%E6%9C%AC%E4%B8%AD%E7%9A%84%20rm%20%E5%91%BD%E4%BB%A4%E4%B8%8D%E9%80%82%E7%94%A8%E4%BA%8E%E5%8F%98%E9%87%8F.png)
我正在编写一个 bash 脚本来创建 mysql 数据库的备份。其实我想删除旧的。
因此,我使用变量创建脚本以实现可维护性。
整个脚本实际上正在工作,唯一不工作的一件事是删除旧的。我以为这将是最简单的部分。
无论如何,这是我的代码,有人可以告诉我出了什么问题吗? rm 命令返回我:rm: impossible de supprimer « /path/to/backup/files/*.gz »: Aucun fichier ou dossier de ce type
这意味着rm: impossible to delete « /path/to/backup/files/*.gz »: no files or directory of this type
但真正奇怪的是,首先我在教程中找到了该脚本
第二,如果我在 shell 命令中启动“rm /path/to/backup/files/*.gz”,这将起作用并删除所有 .gz 文件(如预期)
#!/bin/bash
USER="***"
PASSWORD="****"
OUTPUT="/path/to/backup/files"
rm "$OUTPUT/*.gz"
databases=`mysql --user=$USER --password=$PASSWORD -e "SHOW DATABASES;" | tr -d "| " | grep -v Database`
for db in $databases; do
if [[ "$db" != "information_schema" ]] && [[ "$db" != _* ]] && [[ "$db" != "performance_schema" ]] ; then
echo "Dumping database: $db"
mysqldump --force --opt --user=$USER --password=$PASSWORD --databases $db > $OUTPUT/`date +%Y%m%d`.$db.sql
gzip $OUTPUT/`date +%Y%m%d`.$db.sql
fi
done
谢谢你,
答案1
这
rm "$OUTPUT/*.gz"
shell 命令行告诉 shell 使用/bin/rm
两个参数执行:rm
和/path/to/backup/files/*.gz
。
空格、"
和$
是 shell 语言语法中的特殊字符。空格用于分隔命令参数,"
用于引用其他特殊字符(不是全部,$
例如仍然是特殊字符),如*
上面的那样,并$
用于某些扩展(例如$OUTPUT
您在此处使用的参数扩展)。
rm
启动后将尝试删除该/path/to/backup/files/*.gz
文件。如果该文件不存在(就像您的情况一样),它将报告错误。
当你写:
rm /path/to/backup/files/*.gz
或者
rm "$OUTPUT"/*.gz
由于*
这次没有被引用,它会触发 shell 的另一个特殊功能,称为通配符或文件名生成或文件名扩展。 shell 尝试将包含该*
字符的单词扩展到与该模式匹配的文件名列表。
因此,如果/path/to/backup/files
包含 aa.gz
和b.gz
文件,shell 实际上将rm
使用 3 个参数进行调用:rm
,/path/to/backup/files/a.gz
这/path/to/backup/files/b.gz
看起来更像您想要的。
请注意,它$OUTPUT
本身仍然需要被引用,否则如果它包含 的字符,它最终可能会被分割,$IFS
或者如果它包含任何通配符(如*
上面的那样),它也会受到通配符的影响。
习惯写作也是一个好主意:
rm -- "$OUTPUT"/*.gz
这里$OUTPUT
恰好以 开头/
,所以没关系,但是例如您更改$OUTPUT
为的那一天,它将停止工作,因为这将被视为选项。-foo-
-foo-/...
rm
如果脚本不是交互式的,您可能需要将该-f
选项添加到rm
.这将禁用所有用户提示,并在没有匹配文件的情况下删除错误(大多数 shell,当 glob 不匹配时,将模式按原样传递给应用程序,并且rm -f
当要求删除不匹配的文件时不会抱怨首先就不存在)。
答案2
另一种方法是将 rm 与 find 和/或 xargs 结合起来。这些是一些替代方案:
find "$output" -name *.gz -type f -delete
find "$output" -name "*.gz" -type f -exec rm '{}' \;
find "$output" -name *.gz -type f -print0 | xargs -0 rm
PS:输入f表示查找文件。
默认情况下 find 搜索所有子目录。如果需要,您可以使用 maxdepth 选项将查找操作限制为当前目录:
find "$output" -maxdepth 1 -name "*.gz" -type f -exec rm '{}' \;
如果您需要继续使用 rm 和变量,这对我有用:
out="/home/gv/Desktop/PythonTests/appsfiles";rm "$out"/*.txt
rm: remove regular file '/home/gv/Desktop/PythonTests/appsfiles/a.txt'? y
rm: remove regular file '/home/gv/Desktop/PythonTests/appsfiles/a ver 1.txt'? y
rm: remove regular file '/home/gv/Desktop/PythonTests/appsfiles/b.txt'? y
rm: remove regular file '/home/gv/Desktop/PythonTests/appsfiles/c.txt'? y
rm: remove regular file '/home/gv/Desktop/PythonTests/appsfiles/d.txt'? y
答案3
尝试获取这些文件然后删除它们:
ARCS=`ls $OUTPUT | grep "\.gz$"`
for _arch in $ARCS; do
rm -f $_arch
done