【问题标题】:Shell Script and spaces in pathShell 脚本和路径中的空格
【发布时间】:2011-12-29 06:53:29
【问题描述】:

我有更大的 shell 脚本来处理不同的事情。

它将通过以下方式获得自己的位置...

BASEDIR=`dirname $0`/..
BASEDIR=`(cd "$BASEDIR"; pwd)`

然后将使用 BASEDIR 创建其他变量,例如

REPO="$BASEDIR"/repo

但问题是,如果路径包含当前执行的空格,则此 shell 脚本不起作用。

所以问题是:是否存在解决该问题的好方法?

【问题讨论】:

  • 这应该是posix,因为它应该在尽可能多的unix上运行...在这里你可以看到我的意思的脚本(它被用作模板)。 svn.codehaus.org/mojo/trunk/mojo/appassembler/…
  • 我在bash 和dash(Ubuntu 用于sh)中运行了上面的命令,其父目录的名称包含空格。它似乎工作得很好。如果您从有问题的目录中的终端运行命令,然后运行 ​​echo "$REPO" 会发生什么?我猜你忘了在某处引用"$REPO"。
  • Full0 引用的子shell 通常是您想要的。完整引用$0 肯定是个好主意。一个更完整的例子会很有帮助。

标签: shell


【解决方案1】:

请务必对可能包含空格的任何内容进行双引号:

BASEDIR="`dirname $0`"
BASEDIR="`(cd \"$BASEDIR\"; pwd)`"

【讨论】:

    【解决方案2】:

    答案是“到处引用。”

    如果你传入的路径中有空格,那么dirname $0 将失败。

    $ cat quote-test.sh
    #!/bin/sh
    
    test_dirname_noquote () {
            printf 'no quotes: '
            dirname $1
    }
    test_dirname_quote () {
            printf 'quotes: '
            dirname "$1"
    }
    
    test_dirname_noquote '/path/to/file with spaces/in.it'
    test_dirname_quote '/path/to/file with spaces/in.it'
    
    $ sh quote-test.sh
    no quotes: usage: dirname string
    quotes: /path/to/file with spaces
    

    另外,试试这个有趣的例子

    #!/bin/sh
    
    mkdir -p /tmp/foo/bar/baz
    cd /tmp/foo
    ln -s bar quux
    cd quux
    cat >>find-me.sh<<"."
    #!/bin/sh
    
    self_dir="$(dirname $0)"
    base_dir="$( (cd "$self_dir/.." ; pwd -P) )"
    repo="$base_dir/repo"
    
    printf 'self: %s\n' "$self_dir"
    printf 'base: %s\n' "$base_dir"
    printf 'repo: %s\n' "$repo"
    .
    
    sh find-me.sh
    
    rm -rf /tmp/foo
    

    运行结果:

    $ sh example.sh
    self: .
    base: /tmp/foo
    repo: /tmp/foo/repo
    

    【讨论】:

      【解决方案3】:

      像这样引用你的完整变量:

      REPO="$BASEDIR/repo"
      

      【讨论】:

        【解决方案4】:

        没有可靠和/或可移植的方式来正确执行此操作。

        请参阅 How do I determine the location of my script? 了解原因

        最佳答案如下,这仍然取决于操作系统

        BASEDIR=$(readlink -f $0)

        然后您可以执行 REPO="$BASEDIR"/repo 之类的操作,只需确保像您一样引用您的变量即可。

        【讨论】:

          【解决方案5】:

          对我来说非常好用。您如何使用REPO?什么特别对您“不起作用”?

          我测试过

          #!/bin/sh
          BASEDIR=`dirname $0`/..
          BASEDIR=`(cd "$BASEDIR"; pwd)`
          REPO="$BASEDIR"/repo
          echo $REPO
          

          在“.../a b/c d”目录中。它按预期输出".../a b/repo"。

          请给出您收到的具体错误...“不起作用”的错误报告是最没用的错误报告,每个程序员都非常讨厌它。

          【讨论】:

            【解决方案6】:

            在 unix 的目录名称中使用空格总是一个问题,因此如果可以通过使用下划线来避免它们,这可以防止许多奇怪的脚本行为。

            我不清楚您为什么将 BASEDIR 设置为包含当前脚本 (..) 的目录的父目录,然后在更改为该目录后将其重置

            目录的路径应该仍然有效,如果它有..

            例如/home/trevor/data/../repo

            BASEDIR=`dirname $0`/..
            

            我认为,如果您回显 $REPO,它应该正确分配路径,因为您在分配它时使用了引号,但是如果您尝试在脚本中的其他地方使用 $REPO,您也需要在其周围使用双引号.

            例如

            #!/bin/ksh
            
            BASEDIR=`dirname $0`/..
            $REPO="$BASEDIR"/repo
            
            if [ ! -d ["$REPO"] 
            then
              echo "$REPO does not exist!"
            fi
            

            【讨论】:

              【解决方案7】:

              使用语音标记如下:

               BASEDIR=`dirname "${0}"`/..
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2011-08-16
                • 2013-02-09
                • 1970-01-01
                • 2011-07-15
                • 2012-08-07
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多