Mac Shell脚本获取主目录

时间:2012-06-22 18:06:33

标签: macos bash cp home-directory

我需要在我的shell脚本中获取主目录,以便我的同事可以运行它。我的shell做的很简单,它只将一些目录复制到另一个目录。我用过:

  

$ HOME,
  $(WHOAMI)
  即便如此:
  ABSPATH = $(cd“$(dirname”$ 0“)”; pwd),

但是当我使用这样的变量时:

  

DIR = $ ABSPATH / folder / afolder / bfolder /

并运行它我收到了:

  

/Users/theUser/Desktop/FusionTest.command:line 14:/ Users / theUser / Desktop / folder / afolder / bfolder:是一个目录
  复制到   用法:cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file target_file          cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file ... target_directory   注销
  [流程已完成]

我正在使用命令cp -r复制所有文件和目录。

我错过了什么?或者我该怎么做?

4 个答案:

答案 0 :(得分:6)

由于错误消息暗示-r是递归复制的错误标志。您想要的标志是-R(标志区分大小写)。至于主目录,$HOME应始终有效。

答案 1 :(得分:4)

在这里谈谈几件事:

  1. Macs如何处理HOME目录以及检索实际HOME目录的方法(如果已取消设置)。
  2. 如何正确使用命令行参数,因为Linux上的GNU cp命令允许您以错误的方式执行,这导致了很多问题。
  3. 如何在脚本中使用set -xv进行调试。这将帮助您调试大约90%的shell脚本错误。
  4. 我认为你的剧本实际上是错误的。不幸的是,由于缺乏信息,这是一个疯狂的猜测,但这是一个非常好的猜测。

  5. Macs如何处理主目录

    Mac OS X是一个真正的Unix版本。事实上,它甚至比Linux还要多。因此,它应该与几乎所有系统完全兼容。

    Mac主目录存储在/Users目录下。在Mac使用的默认BASH shell中(甚至在旧的Turbo Csh中),您可以使用~作为$HOME的别名。

     $ echo "$HOME"   # Use quotes around directory and file names to avoid 
     $                # problems with white spaces.
     $ echo ~         # Echos the `$HOME` directory.
    

    如果有人更改了HOME环境变量,您可以使用~userName获取HOME目录的正确值:

    $ echo $HOME
    /Users/david
    HOME=/tmp
    $ echo $HOME
    /tmp
    $ echo ~
    /tmp
    $ echo ~david
     /Users/david
    $ HOME=~david   #Fixed!
    

    命令行参数

    该错误可能与您计算机的 Macness 无关。这可能是几乎所有计算机上都会出现的标准问题。 Mac的cp命令采用-r-R命令。与Linux系统上的GNU cp不同,Mac正确处理命令行参数

    例如,在Linux上,这是可以接受的:

    $ cp "$dir" "$dir2" -r
    

    在Unix系统上,这可能会失败。命令后需要-r参数:

    $ cp -r "$dir" "$dir2"
    

    如果您正在执行第一个示例中的cp命令,它将无法在Unix上运行,并且无法在Mac上运行。

    调试Shell脚本

    现在,我们已经完成了一些预备工作,让我们来看看如何调试你的问题......

    set -xv放在第14行之前(可能需要几行才能确定)。这将打开脚本调试。 -x参数将在执行行之前使用插值回显命令行。这样,您可以看到正在执行的实际命令。

    -v参数将按原样回显行,而不进行插值。这样,您可以看到命令的外观,并可能在环境变量的设置中检测到错误。

    这是一个简单的脚本:

     name="David"
     echo "Hello $name!"
    

    执行脚本,我们得到:

     $ test.sh
     Hello David!
     $
    

    现在,我会这样做:

     set -xv
     name="David"
     echo "Hello $name!"
     set +xv     #Turns off the -xv flags
    

    现在,我会得到这个:

     $ ./test.sh
     name="David"
     + name=David
     echo "Hello $name!"
     + echo 'Hello David!'
     Hello David!
    

    另一个巧妙的技巧是将PS4设置为“${LINENO}:”。这将在每行前面加上行号而不仅仅是+,如上所述:

    可能的解决方案

    我感觉问题是你有一个带空格的目录名。引用目录和文件名以防止这些空格导致您出现问题:

    my_pictures=$HOME/"My Pictures"
    cp -R $my_pictures $target     #Won't work due to the space between "My" & "Pictures"
    cp -R "$my_pictures" "$target" #The quotes solve the problem.
    

    结论

    不要担心您的Mac 不同。它只是另一个Unix系统。确保您正确使用命令行参数cp -R $dir1 $dir2而不是cp $dir $dir2 -R。使用set -xv帮助您找到错误,并养成引用环境变量的习惯,因为环境变量值中的空格或制表符可能导致程序失败。


    关于Mac OS X的注意事项 - Lion

    根据联机帮助页,-r不再作为选项记录。但它确实有效。根据手册页:

      

    cp实用程序的历史版本有-r选项。此实现支持该选项;但是,强烈建议不要使用它,因为它无法正确复制特殊文件,符号链接或横笛。

    但是,cp -R应该适用于Linux,并且在Mac OS X中作为递归复制标记记录。

答案 2 :(得分:1)

我不喜欢〜脚本和$ HOME有时取决于你正在使用的shell - 可能不在OSX上,但我不在乎..

某处某处,系统会记录用户主目录的位置,并设置$ HOME。

具体来说,我经常试图找到另一个用户的主目录(并且再次不是脚本中〜缩写的粉丝 - 称之为偏好) 对于OSX,我使用它 -

 finger $username | awk '/^Directory/ {print $2}'

在其他地方,我通常grep / etc / passwd,但想一想,手指可能会更普遍。

这是我快速而又肮脏的答案。如果你知道OSX内部更好 - 但是关心因素会有更好的解决方案吗?这对我有用

答案 3 :(得分:0)

$ HOME应该设置,但不保证。用户可以覆盖此变量。另一种选择是使用getent

IFS=: read -r _ _ _ _ _ homedir _ < <(getent passwd myuser)
echo "$homedir"