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:
HOME
directories and a way to retrieve the actual HOME
directory if it has been unset. cp
command on Linux allows you to do it the wrong way, and that has caused a lot of problems. set -xv
for debugging in your script. This will help you debug about 90% of the shell script errors you get. 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!
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.
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:
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.
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.
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.