在shell脚本中,你应该改变当前目录吗?

4
我一直认为当前目录是供用户使用的,而不是脚本,因为它依赖于用户的位置,并且每次执行脚本时可能会有所不同。因此,当我遇到Java jar工具的-C选项时,有些困惑。
对于那些不知道的人,-C选项用于在指定要包含在jar文件中的文件/文件夹之前使用。由于文件/文件夹的路径在jar文件中被复制,所以-C选项在包含文件之前更改目录:
换句话说:
jar -C flower lily.class

将创建一个包含 lily.class 文件的 jar 包,而:

jar flower/lily.class

将在jar文件中创建一个名为flower的文件夹,其中包含lily.class


对于我正在制作的jar-ing脚本,我想使用Bourne通配符folder/*,但这会使得使用-C变得不可能,因为它只适用于下一个立即参数。

因此,唯一可以使用通配符的方法是从当前目录运行;但我仍然对在脚本中更改和使用当前目录感到不安。

在脚本中使用当前目录有什么缺点吗?也许因为某种原因而被反感了吗?


2
我不明白为什么会有敌意,因为cd是局限于子进程的。试试这个命令:pwd; (cd ..; pwd); pwd,你会发现当你退出子shell(由括号表示)时,当前目录回到了开始的位置。无论脚本做什么(除非你使用source而不是执行它),对用户来说都没有影响。 - Amadan
2
没关系,完成后把它放回原来的位置就行。 - Tony Hopkinson
1
goto语句是一种可怕的东西,因为它是无限制的,早期的程序设计中就是这样。你可以从一个子程序跳到另一个子程序,这会破坏环境并对后来阅读代码的人造成严重的脑损伤。但在特定情况下使用它们是完全可以接受的。有趣的是,它们被接受的情况几乎完美地与可以使用异常的地方相吻合(这保留了程序的层次结构)。你可以注意到这里发生的同样的事情 - cd命令不能影响超级进程,而子进程是你自己的责任。 - Amadan
2
还有其他支持更改目录的程序,例如tar -C dirnamefind -execdir - Dennis Williamson
@Amadan,最近我发现goto很有趣,因为在汇编语言中,由于没有循环,你基本上只能使用goto来控制流程。 - Hawken
显示剩余2条评论
1个回答

1

我认为从shell脚本更改当前目录并没有什么本质上的问题。如果单独考虑,当然不会导致任何不良后果。

事实上,我有一个标准脚本用于启动基于Java的服务器,而第一行就是:

cd `dirname $0`

这样可以确保脚本中其余的命令在包含脚本文件本身的目录中执行(当单个机器托管多个服务器实例时非常有用),而不管脚本实际从哪里调用。如果在脚本中不更改当前目录,则只有在用户记得在运行脚本之前手动cd到相应的目录时,它才能正常工作。

在这种情况下,从脚本内部执行cd操作可以从服务器启动/关闭过程中删除一个手动步骤,从而使事情稍微不那么容易出错。

所以像大多数事情一样,这种东西有合法的用途。我相信也有一些可疑的用途。这真的取决于您特定用例的最合适的内容。这是我无法评论的...我总是让maven为我构建JAR文件。


是的,\dirname $0``也是我使用的方法,我在想是否应该这样做。 - Hawken
1
@Hawken:请参阅BashFAQ/028,了解脚本的位置。 - Dennis Williamson
1
@Hawken - “是否”这个问题真的取决于你。虽然根据Dennis上面的链接,可能会出现一些非常晦涩的警告,但没有什么可以阻止你这样做。你只需要决定是否愿意接受这些警告。就我个人而言,它们并不困扰我,因为我更喜欢一个自包含的服务器部署,而不是一个强壮的解决方案,如果有人在我运行脚本时将其“mv”掉,它就不会崩溃。如果另一个系统管理员正在移动我的东西,那么我就有更严重的问题要担心了。 - aroth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接