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

vek*_*kah 8 bash shell-script rm variable

我正在做一个 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
Run Code Online (Sandbox Code Playgroud)

谢谢,

Sté*_*las 14

rm "$OUTPUT/*.gz"
Run Code Online (Sandbox Code Playgroud)

shell 命令行告诉 shell/bin/rm使用两个参数执行:rm/path/to/backup/files/*.gz.

空格"$是 shell 语言语法中的特殊字符。空格用于分隔命令参数,"用于引用其他特殊字符(并非全部,$例如仍然是特殊字符),如*上述,并$用于某些扩展(如$OUTPUT您在此处使用的参数扩展)。

rm一旦启动将尝试删除该/path/to/backup/files/*.gz文件。如果该文件不存在(如您的情况),它将报告错误。

当你写:

rm /path/to/backup/files/*.gz
Run Code Online (Sandbox Code Playgroud)

或者

rm "$OUTPUT"/*.gz
Run Code Online (Sandbox Code Playgroud)

由于*这次没有被引用,它触发了 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
Run Code Online (Sandbox Code Playgroud)

这里$OUTPUT碰巧以 开头/,所以很好,但是例如,在您更改$OUTPUT为的那一天-foo-,它将停止工作,因为这-foo-/...将被rm视为选项。

如果脚本不是交互式的,您可能需要将该-f选项添加到rm. 这将禁用所有用户提示,并在没有匹配文件时删除错误(大多数 shell,当 glob 没有匹配时,将模式按原样传递给应用程序,并且rm -f在被要求删除不匹配的文件时不会抱怨) '首先不存在)。

  • 总结一下:只需要引用变量。引用 `*` 会阻止它进行通配。 (7认同)

Geo*_*iou 3

另一种方法是将 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
Run Code Online (Sandbox Code Playgroud)

PS:输入f表示查找文件。

默认情况下 find 搜索所有子目录。如果需要,您可以使用 maxdepth 选项将查找操作限制为当前目录:

find "$output" -maxdepth 1 -name "*.gz" -type f -exec rm '{}' \;
Run Code Online (Sandbox Code Playgroud)

如果您需要继续使用 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
Run Code Online (Sandbox Code Playgroud)

  • 实际上,“rm”对于变量来说效果很好 (3认同)