简体   繁体   中英

Mac Shell script get home directory

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:

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

but when I use the variable like this:

DIR= $ABSPATH/folder/afolder/bfolder/

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]

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

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

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

Talk about several things here:

  1. How Macs handle HOME directories and a way to retrieve the actual HOME directory if it has been unset.
  2. How to use command line parameters correctly because the GNU cp command on Linux allows you to do it the wrong way, and that has caused a lot of problems.
  3. How to use set -xv for 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.

How Macs Handle Home Directories

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.

The Mac home directory are stored under the /Users directory. In the default BASH shell that Mac uses (and even in the old Turbo Csh), you can use ~ as an alias to the $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 HOME environment variable, you can use ~userName to get the correct value of the HOME directory:

$ 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 Macness of your computer. It's probably a standard problem you'd find on almost any computer. The Mac's cp command takes either the -r or -R command. Unlike GNU's cp which is found on Linux systems, the Mac handles the command line parameters correctly .

For example, on Linux, this is acceptable:

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

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

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

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

Debugging Shell Scripts

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

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

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

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 PS4 to " ${LINENO}: ". That will prepend each line with the line number rather than just a + as above:

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 $dir2 and not cp $dir $dir2 -R . Use set -xv to 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.


Note on Mac OS X - Lion

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

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.

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

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..

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

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 --

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

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

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

$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 .

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM