在这里谈几件事:
- Mac 如何处理
HOME
目录以及在未设置实际目录的情况下检索实际HOME
目录的方法。
- 如何正确使用命令行参数,因为
cp
Linux 上的 GNU 命令允许您以错误的方式进行操作,这导致了很多问题。
- 如何
set -xv
在脚本中用于调试。这将帮助您调试您遇到的大约 90% 的 shell 脚本错误。
- 我认为您的脚本实际上是错误的。不幸的是,由于缺乏信息,这是一个疯狂的猜测,但这是一个很好的猜测。
Mac 如何处理主目录
Mac OS X 是真正的 Unix 版本。事实上,它甚至比 Linux 更像 Unix。因此,它应该与几乎所有系统都相当兼容。
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
or-R
命令。与cp
Linux 系统上的 GNU 不同,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}:
”。这将在每一行前面加上行号,而不仅仅是+
上面的 a:
可能的解决方案
我有一种感觉,问题在于您的目录名称中带有空格。引用目录和文件名以防止这些空格给您带来问题:
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 中作为递归复制标志记录。