【问题标题】:Getting the path where an OS X shell script is located within the script...when the path has whitespace获取脚本中 OS X shell 脚本所在的路径...当路径有空格时
【发布时间】:2011-08-16 21:36:34
【问题描述】:

我在 Bash 脚本中使用它来获取运行脚本的路径。在 OS X 中双击 .command 文件是必需的。

#!/bin/bash
BASEDIR=$(dirname $0)
cd $BASEDIR

问题是当路径有空格时它不起作用。你会如何解决这个问题?

【问题讨论】:

标签: macos bash


【解决方案1】:
#!/bin/bash
BASEDIR="$( dirname "$0" )"
cd "$BASEDIR"

【讨论】:

    【解决方案2】:

    你必须使用引号:

    #!/bin/bash
    BASEDIR=$(dirname $0)
    cd "$BASEDIR"
    

    【讨论】:

    • 还是不行,问题出在 with dirname: usage: dirname path
    • 检查 $PWD 是否匹配 $0 路径。这可能会在 basedir 中产生空结果
    • 您还需要在 $0 组件周围加上引号,以便它作为单个参数而不是多个参数出现在 dirname 中。
    • 您需要在任何内容周围加上引号,以防止包含空格的变量出现副作用..请参考此答案stackoverflow.com/a/5857203/1032370
    【解决方案3】:

    我正在使用它来启动我的 plackup 服务器,我的:“run.command”

    DIR=`dirname "$0"`
    cd "$DIR"
    plackup -r
    

    【讨论】:

      【解决方案4】:

      这可能很糟糕。先前的答案都不会解决符号链接。 这个应该是相当可移植的(用破折号和 bash 双重检查),并且将遍历路径中带有空格的符号链接:

      #!/bin/sh # dash bash ksh # !zsh (issues). G. Nixon, 12/2013. Public domain.
      
      ## 'linkread' or 'fullpath' or (you choose) is a little tool to recursively
      ## dereference symbolic links (ala 'readlink') until the originating file
      ## is found. This is effectively the same function provided in stdlib.h as
      ## 'realpath' and on the command line in GNU 'readlink -f'.
      
      ##===-------------------------------------------------------------------===##
      
      for argv; do :; done # Last parameter on command line, for options parsing.
      
      ## Error messages. Use functions so that we can sub in when the error occurs.
      
      recurses(){ printf "Self-referential:\n\t$argv ->\n\t$argv\n" ;}
      dangling(){ printf "Broken symlink:\n\t$argv ->\n\t"$(readlink "$argv")"\n" ;}
      errnoent(){ printf "No such file: "$@"\n" ;} # Borrow a horrible signal name.
      
      # Probably best not to install as 'pathfull', if you can avoid it.
      
      pathfull(){ cd "$(dirname "$@")"; link="$(readlink "$(basename "$@")")"
      
      ## 'test and 'ls' report different status for bad symlinks, so we use this.
      
       if [ ! -e "$@" ]; then if $(ls -d "$@" 2>/dev/null) 2>/dev/null;  then
          errnoent 1>&2; exit 1; elif [ ! -e "$@" -a "$link" = "$@" ];   then
          recurses 1>&2; exit 1; elif [ ! -e "$@" ] && [ ! -z "$link" ]; then
          dangling 1>&2; exit 1; fi
       fi
      
      ## Not a link, but there might be one in the path, so 'cd' and 'pwd'.
      
       if [ -z "$link" ]; then if [ "$(dirname "$@" | cut -c1)" = '/' ]; then
         printf "$@\n"; exit 0; else printf "$(pwd)/$(basename "$@")\n"; fi; exit 0
       fi
      
      ## Walk the symlinks back to the origin. Calls itself recursivly as needed.
      
       while [ "$link" ]; do
         cd "$(dirname "$link")"; newlink="$(readlink "$(basename "$link")")"
         case "$newlink" in
          "$link") dangling 1>&2 && exit 1                                       ;;
               '') printf "$(pwd)/$(basename "$link")\n"; exit 0                 ;;
                *) link="$newlink" && pathfull "$link"                           ;;
         esac
       done
       printf "$(pwd)/$(basename "$newlink")\n"
      }
      
      ## Demo. Install somewhere deep in the filesystem, then symlink somewhere 
      ## else, symlink again (maybe with a different name) elsewhere, and link
      ## back into the directory you started in (or something.) The absolute path
      ## of the script will always be reported in the usage, along with "$0".
      
      if [ -z "$argv" ]; then scriptname="$(pathfull "$0")"
      
      # Yay ANSI l33t codes! Fancy.
       printf "\n\033[3mfrom/as: \033[4m$0\033[0m\n\n\033[1mUSAGE:\033[0m   "
       printf "\033[4m$scriptname\033[24m [ link | file | dir ]\n\n         "
       printf "Recursive readlink for the authoritative file, symlink after "
       printf "symlink.\n\n\n         \033[4m$scriptname\033[24m\n\n        "
       printf " From within an invocation of a script, locate the script's "
       printf "own file\n         (no matter where it has been linked or "
       printf "from where it is being called).\n\n"
      
      else pathfull "$@"
      fi
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-15
        • 2014-11-20
        • 1970-01-01
        • 1970-01-01
        • 2018-04-13
        • 2019-01-27
        • 2011-01-10
        • 2011-04-04
        相关资源
        最近更新 更多