`ls` 命令将我的带空格的目录解释为多个目录

The `ls` command is interpreting my directory with spaces as multiple directories

我正在尝试传递一个执行 ls 的动态命令作为一个字符串,该字符串列出了包含空格的目录的文件。但是,无论我做什么,我的 ls 命令总是将包含空格的一个目录解释为多个目录。

考虑我的 shell 脚本的以下简化版本:

#!/bin/sh

export WORK_DIR="/Users/jthoms/Dropbox (My Company)/backup-jthoms/Work"
echo "WORK_DIR=$WORK_DIR"

export LS_CMD="ls -A \"$WORK_DIR/dependencies/apache-tomcat-8.0.45/logs\""
echo "LS_CMD=$LS_CMD"

if [ -n "$($LS_CMD)" ]
then
    echo "### Removing all logs"
    sudo rm "$WORK_DIR/dependencies/apache-tomcat-8.0.45/logs/*"
else
    echo "### Not removing all logs"
fi

此脚本产生以下输出:

WORK_DIR=/Users/jthoms/Dropbox (My Company)/backup-jthoms/Work
LS_CMD=ls -A "/Users/jthoms/Dropbox (My Company)/backup-jthoms/Work/dependencies/apache-tomcat-8.0.45/logs"
ls: "/Users/jthoms/Dropbox: No such file or directory
ls: (My: No such file or directory
ls: Company)/backup-jthoms/Work/dependencies/apache-tomcat-8.0.45/logs": No such file or directory
### Not removing all logs

如何正确转义我的 shell 变量,以便 ls 命令将我的目录解释为包含空格的单个目录而不是多个目录?

我最近更改了这个脚本,该脚本过去适用于不包含空格的目录,但现在不适用于这种新情况。我正在 MacOSX 上开发 Bash。我已经尝试过各种形式的转义,各种 Google 搜索并在此处搜索类似的问题,但无济于事。请帮忙。

变量用于数据。函数用于代码。

# There's no apparent need to export this shell variable.
WORK_DIR="/Users/jthoms/Dropbox (My Company)/backup-jthoms/Work"
echo "WORK_DIR=$WORK_DIR"

ls_cmd () {
  ls -A ""/dependencies/apache-tomcat-8.0.45/logs
}

if [ -n "$(ls_cmd "$WORK_DIR")" ]; then
then
  echo "### Removing all logs"
  sudo rm "$WORK_DIR/dependencies/apache-tomcat-8.0.45/logs/"*
else
  echo "### Not removing all logs"
fi

但是,您根本不需要 ls(通常,您应该 avoid parsing the output of ls)。例如,

find "$WORK_DIR/dependencies/apache-tomcat-8.0.45/logs/" -type f -exec rm -rf {} +

你可以使用

# ...
if [ -n "$(eval "$LS_CMD")" ]
# ...

http://mywiki.wooledge.org/BashFAQ/050

甚至

# ...
if [ -n "$(bash -c "$LS_CMD")" ]
# ...

但是您最好使用专用函数 and/or 甚至是针对您的问题的更具体的函数(在这些情况下使用 find 而不是 ls 通常是个好主意,请参阅 this question).

的答案中的一些示例

使用数组而不是字符串来存储命令:

ls_cmd=(ls -A "$WORK_DIR/dependencies/apache-tomcat-8.0.45/logs")
echo "ls_cmd=${ls_cmd[*]}"

if [ -n "$("${ls_cmd[@]}")" ]; then …

(最后一行突出显示的语法不正确且具有误导性:我们没有取消引用 ${ls_cmd[@]};实际上,我们在这里通过子 shell 使用嵌套引号。)

这样,分词就不会干扰您的命令。

请注意,您无法导出数组。但是你不需要,在你的代码中。

正如其他人所指出的,在这里使用函数通常是更好的主意。更重要的是,you shouldn’t parse the output of ls。总有更好的选择。