为什么我的 'rm' 命令在我的 mac 终端中运行良好,但在 shell 脚本中运行不佳?

为什么我的 'rm' 命令在我的 mac 终端中运行良好,但在 shell 脚本中运行不佳?

我有一个名称包含空格的目录。我需要删除这个特定目录的内容。\在删除内容之前,我正在转义目录名称中的空格。该rm命令在终端上工作正常,但如果我在 Shell 脚本中使用它,它就不起作用。我明白了没有这样的文件或目录错误。

例如,我有以下目录结构, Users/Neeraj/Documents/temp dir/dir with spaces/a.txt 我需要删除目录“dir with space”内的所有内容。我的 Shell 脚本中的代码如下所示

#!/bin/sh
TEMP_DIR="$HOME/Documents/temp dir/dir with spaces"
TEMP_DIR=$(echo $TEMP_DIR | sed 's/ /\\ /g')
COMMAND="rm -r $TEMP_DIR/*"
echo "Command: $COMMAND"
rm -r "$TEMP_DIR"/*

当我运行这个脚本时,我得到没有这样的文件或目录错误,而如果我只是复制它并从终端运行相同的命令则可以正常工作。

输出:

Command: rm -r /Users/Neeraj/Documents/temp\ dir/dir\ with\ spaces/*
rm: /Users/Neeraj/Documents/temp\ dir/dir\ with\ spaces/*: No such file or directory

这样做的正确方法是什么?

笔记: 我使用的是 macOS

答案1

@Olorins 答案是这个问题的正确答案,但我想添加更多信息为什么这是行不通的:


您可以使用以下任一方法:

rm "dir with spaces"
rm dir\ with\ spaces
dir="dir with spaces"; rm "$dir"

但这些行不通:

dir="dir\ with\ spaces";
rm "$dir" # the backslash will be taken literally inside quotes 
rm $dir # this should work, shouldn't it? Please read below.

后一个选择一开始对我来说并不直观。但是 bash 扩展了变量内容,添加了一些引用执行前

您可以使用set -x查看实际执行的内容:

( var="a\ b"; set -x; echo $var; )
+ echo 'a\' b
a\ b

虽然输出看起来不错,但空格仍然未转义,因为\被单引号包围。

答案2

您正在使用两个引号反斜杠转义。仅使用引用就可以很好地工作。

这应该足够了:

TEMP_DIR="$HOME/Documents/temp dir/dir with spaces"
COMMAND="rm -r $TEMP_DIR/*"
echo "Command: $COMMAND"
rm -r "$TEMP_DIR"/*

在这种情况下,反斜杠和引号都应该由 shell 处理,以防止它分割目录名。当您同时使用两者时,shell 会保留两个空格引号内的反斜杠,因此rm实际上进入了.../temp\ dir/dir\ with\ spaces/...它应该得到的参数.../temp dir/dir with spaces/...

当您复制打印的命令时,shell 会看到反斜杠而不需要额外的引号,因此它会保留受反斜杠保护的空格并删除反斜杠,因此rm.../temp dir/dir with spaces/...进入参数。

相关内容