我正在将一些批处理脚本转换为 shell 脚本。批处理脚本具有 cd 命令,但仍然使用绝对路径。
foo.bat:
pushd
cd C:\some\directory
copy C:\some\directory\foo.txt C:\some\other\directory
popd
我认为此脚本中的 cd 是多余的,因为正在复制的文件是使用绝对路径调用的。我需要将其转换为 shell 脚本。我有以下两个选择:
测试1.sh:
cp /some/directory/foo.txt /some/other/directory
测试2.sh:
cd /some/directory
cp foo.txt /some/other/directory
第一个仅使用 cp 和绝对路径,第二个使用 cd 和相对路径。
我的问题是:就在 shell 脚本中使用路径而言,这两个示例中哪一个是更好的做法?
作为一个附带问题,这些示例中是否需要 pushd/popd ?
答案1
调用脚本不一定是坏事cd
,但应该谨慎行事。多次调用会cd
产生“代码味道”。绝对路径通常更可取。
cd
可能会失败。请务必正确处理错误。
调用 后cd
,相对路径将变得无效。特别是,如果您正在编写一个包装器脚本来准备一些内容,然后运行另一个命令,则永远不要调用cd
:用户可能依赖于在原始目录中运行的命令。如果您的脚本使用在命令行上传递的文件名,它们通常是相对于原始目录的;你可以"$PWD/"
在它们前面加上绝对值,但是如果出现问题,这会导致错误消息。
该变量PWD
始终包含当前目录,因此您可以将其保存到另一个变量中,并通过cd
稍后调用更改回来。但是,请注意,这在某些边缘情况下可能会失败,例如以低权限运行的脚本不允许更改回其原始目录,或者在脚本运行时移动的目录。
请注意相对路径:它们可以以 开头,如果您不采取预防措施,-
以 开头的命令参数将被解释为选项。-
绝对路径则不存在这个问题。
答案2
据我的经验,这主要取决于您的需求和偏好,
您会发现很多文档将其留给用户。这是我注意到的:
- 绝对路径更清晰:谁将不得不维护/修改您的脚本(您或其他人)将能够知道每次涉及哪些目录;
- 使用绝对路径,您可以确定所涉及的目录是具有您在脚本中编写的确切路径的目录;
- 相对路径较短,但您需要确定您正在使用的子树;
- 您可以在脚本开头用变量替换重复路径来实现简短(例如 /var/log/app/component/module/logfile.log -> $module_log_dir/logfile.log)
正如 thrig 所注意到的,您可以在要执行的命令之前添加对所涉及目录的检查。