bash 脚本中的 rm 命令不适用于变量

bash 脚本中的 rm 命令不适用于变量

我正在编写一个 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.gzb.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

相关内容