bash Mac Shell 脚本获取主目录

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11161793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 02:33:48  来源:igfitidea点击:

Mac Shell script get home directory

macosbashcphome-directory

提问by Rafael Jimeno

I need to get the home directory in my shell script so my coworkers can run it. What my shell does is really simple, it only copy some directories to another. I've used:

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

$HOME,
$(whoami)
even this:
ABSPATH=$(cd "$(dirname "$0")"; pwd),

$HOME,
$(whoami)
甚至这个:
ABSPATH=$(cd "$(dirname "$0")"; pwd),

but when I use the variable like this:

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

DIR= $ABSPATH/folder/afolder/bfolder/

DIR= $ABSPATH/文件夹/文件夹/文件夹/

and run it I receive this:

并运行它我收到这个:

/Users/theUser/Desktop/FusionTest.command: line 14: /Users/theUser/Desktop/folder/afolder/bfolder: is a directory
Copying to usage: cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file target_file cp [-R [-H | -L | -P]] [-fi | -n] [-apvX] source_file ... target_directory logout
[Process completed]

/Users/theUser/Desktop/FusionTest.command:第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 注销
[过程完成]

I'm using the command cp -r to copy all files and directories.

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

Whay I am missing? or how can I do this??

为什么我失踪了?或者我该怎么做?

回答by You

As the error message implies -ris the incorrect flag for recursive copying. The flag you want is -R(flags are case-sensitive). As for the home directory, $HOMEshould always work.

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

回答by David W.

Talk about several things here:

这里说几件事:

  1. How Macs handle HOMEdirectories and a way to retrieve the actual HOMEdirectory if it has been unset.
  2. How to use command line parameters correctly because the GNU cpcommand on Linux allows you to do it the wrong way, and that has caused a lot of problems.
  3. How to use set -xvfor debugging in your script. This will help you debug about 90% of the shell script errors you get.
  4. What I think is actually wrong in your script. Unfortunately, this is a wild guess due to a lack of information, but it's a pretty good guess.
  1. Mac 如何处理HOME目录以及在HOME未设置实际目录的情况下检索实际目录的方法。
  2. 如何正确使用命令行参数,因为cpLinux 上的 GNU命令允许您以错误的方式使用命令行参数,这导致了很多问题。
  3. 如何set -xv在脚本中用于调试。这将帮助您调试大约 90% 的 shell 脚本错误。
  4. 我认为您的脚本中实际上是错误的。不幸的是,由于缺乏信息,这是一个疯狂的猜测,但这是一个很好的猜测。


How Macs Handle Home Directories

Mac 如何处理主目录

Mac OS X is a true Unix version. In fact, it's even more Unix than Linux. Because of this, it should be fairly compatible with almost all systems.

Mac OS X 是真正的 Unix 版本。事实上,它甚至比 Linux 更像 Unix。因此,它应该与几乎所有系统都相当兼容。

The Mac home directory are stored under the /Usersdirectory. In the default BASH shell that Mac uses (and even in the old Turbo Csh), you can use ~as an alias to the $HOME.

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.

If someone changed the HOMEenvironment variable, you can use ~userNameto get the correctvalue of the HOMEdirectory:

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

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

Command Line Parameters

命令行参数

The error probably doesn't have anything to do with the Macnessof your computer. It's probably a standard problem you'd find on almost any computer. The Mac's cpcommand takes either the -ror -Rcommand. Unlike GNU's cpwhich is found on Linux systems, the Mac handles the command line parameters correctly.

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

For example, on Linux, this is acceptable:

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

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

On Unix systems, that would probably fail. You need the -rparameter after the command:

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

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

If you're doing the cpcommand as in the first example, it won't work on Unix and won't work on a Mac.

如果您cp像第一个示例那样执行命令,它将无法在 Unix 上运行,也无法在 Mac 上运行。

Debugging Shell Scripts

调试 Shell 脚本

Now, that we got some preliminaries out of the way, let's look how to debug your problem...

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

Put set -xvbefore line #14 (maybe a few lines before just to be sure). This turns on script debugging. The -xparameter will echo the command line with interpolations before executing the line. This way, you can see what the actual command is being executed.

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

The -vparameter will echo the line as iswithout interpolation. That way, you can see what the command looked like and maybe detect an error in the setting of an environment variable.

-v参数将在没有插值的情况下按原样回显该行。这样,您就可以看到命令的样子,并且可能会检测到环境变量设置中的错误。

Here's a simple script:

这是一个简单的脚本:

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

Executing the script, we get:

执行脚本,我们得到:

 $ test.sh
 Hello David!
 $

Now, I'll do this:

现在,我会这样做:

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

Now, I'll get this:

现在,我会得到这个:

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

Another neat trick is to set PS4to "${LINENO}:". That will prepend each line with the line number rather than just a +as above:

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

The Possible Solution

可能的解决方案

I have a feeling that the problem is that you have a directory name with spaces in it. Quote directory and file names to prevent these spaces from causing you problems:

我有一种感觉,问题在于您的目录名称中包含空格。引用目录和文件名以防止这些空格给您带来问题:

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.

Conclusions

结论

Don't worry about your Mac being different. It's just another Unix system. Make sure that you're using the command line parameters correctly cp -R $dir1 $dir2and not cp $dir $dir2 -R. Use set -xvto help you locate the errors, and get into the habit of quoting your environment variables since a space or tab in the environment variable's value could cause the program to fail.

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



Note on Mac OS X - Lion

Mac OS X 上的注意事项 - Lion

According to the manpage, -ris no longer documented as an option. However it does work. According to the man page:

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

Historic versions of the cp utility had a -r option. This implementation supports that option; however, its use is strongly discouraged, as it does not correctly copy special files, symbolic links, or fife's.

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

However, cp -Rshould work on both Linux and is documented in Mac OS X as the recursive copy flag.

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

回答by Alex Pretty

I don't like ~ in scripts and $HOME fails sometimes depending on the shell you're using - maybe not on OSX, but I don't care..

我不喜欢脚本中的 ~ 并且 $HOME 有时会失败,具体取决于您使用的 shell - 也许不是在 OSX 上,但我不在乎..

Somewhere somehow the system has a record of where a user's home directory is and $HOME is set from that.

不知何故,系统记录了用户的主目录所在的位置,并从中设置了 $HOME。

Specifically, I am usually trying to find the home dir of another user (and again not a fan of ~ abbreviations in scripts - call it preference) For OSX, I use this --

具体来说,我通常试图找到另一个用户的主目录(再次不是脚本中 ~ 缩写的粉丝 - 称之为首选项)对于 OSX,我使用这个 -

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

Everywhere else, I usually grep /etc/passwd, but thinking on it, finger would probably be more universal.

在其他地方,我通常使用 grep /etc/passwd,但仔细想想,finger 可能更通用。

This is my quick and dirty answer. There will be a better solution if you know OSX internal better - but care factor? This works for me

这是我快速而肮脏的答案。如果您更了解 OSX 内部,将会有更好的解决方案 - 但关心因素?这对我有用

回答by jordanm

$HOME should be set, but it is not guaranteed. It is possible for a user to override this variable. Another option is to use getent.

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

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