谈论以下几点内容:
- Mac如何处理
HOME
目录,以及如果未设置,检索实际的HOME
目录的方法。
- 如何正确使用命令行参数,因为Linux上的GNU
cp
命令允许您以错误的方式执行它,这导致了很多问题。
- 如何在脚本中使用
set -xv
进行调试。这将帮助您调试约90%的shell脚本错误。
- 我认为您的脚本实际上存在什么问题。不幸的是,由于缺乏信息,这只是一个猜测,但是它是一个相当好的猜测。
Mac如何处理Home目录
Mac OS X是真正的Unix版本。事实上,它比Linux还要更Unix。因此,它应该与几乎所有系统都相当兼容。
Mac home目录存储在/Users
目录下。在Mac使用的默认BASH shell中(甚至在旧的Turbo Csh中),您可以使用~
作为对$HOME
的别名。
$ echo "$HOME"
$
$ echo ~
如果有人更改了HOME
环境变量,你可以使用~userName
来获取正确的HOME
目录值:
$ echo $HOME
/Users/david
HOME=/tmp
$ echo $HOME
/tmp
$ echo ~
/tmp
$ echo ~david
/Users/david
$ HOME=~david
命令行参数
这个错误很可能与你的电脑是否为Mac电脑无关。在几乎任何计算机上,都可能遇到这种标准问题。Mac的cp
命令接受-r
或-R
命令。与Linux系统上的GNU cp
不同,Mac正确处理命令行参数。
例如,在Linux上,以下命令是可接受的:
$ cp "$dir" "$dir2" -r
在Unix系统上,这可能会失败。您需要在命令后添加-r
参数:
$ cp -r "$dir" "$dir2"
如果您像第一个示例中那样执行
cp
命令,它在Unix上不起作用,在Mac上也不起作用。
调试Shell脚本
现在,我们已经解决了一些基础问题,让我们看看如何调试您的问题...
在第14行之前(也许在前面几行),加入
set -xv
。这将打开脚本调试。参数
-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
cp -R "$my_pictures" "$target"
结论
不要担心你的 Mac 是“不同”的。它只是另一个 Unix 系统。确保正确使用命令行参数 cp -R $dir1 $dir2
,而不是 cp $dir $dir2 -R
。使用 set -xv
帮助你定位错误,并养成引用环境变量的习惯,因为环境变量的值中的空格或制表符可能会导致程序失败。
关于 Mac OS X - Lion 的说明
根据 man 页,-r
不再作为选项进行文档记录。但它仍然有效。根据 man 页:
cp 实用程序的历史版本具有 -r 选项。此实现支持该选项;但是,强烈不建议使用它,因为它无法正确复制特殊文件、符号链接或管道。
然而,cp -R
应该在 Linux 上都能正常工作,并在 Mac OS X 中作为递归复制标志进行了记录。
"$HOME"
而不仅仅是$HOME
。 - sorpigal