每个进程都有一个当前目录。当一个进程启动时,它会从其父进程继承当前目录;例如,它不会被设置为包含您正在运行的程序的目录。
如果您想了解更详细的解释,请继续阅读。
当磁盘变得足够大,您不希望将所有文件保存在同一个位置时,操作系统供应商提出了一种结构化文件的方法,即目录。因此,您可以创建新的集合以及这些集合内部的其他新集合(除了某些早期实现不能包含其他目录之外),而不是将所有内容保存在同一个目录中(或者初学者现在被教导叫做“文件夹”)。
从根本上讲,目录只是一种特殊类型的文件,其内容是其他文件的集合,也可以包括其他目录。
在原始的操作系统上,故事就到这里结束了。如果您想打印位于mine
目录中的studies
目录中的2021
目录中的spring_semester
目录中的term_paper.txt
文件,您需要说:
print mine/studies/2021/spring_semester/term_paper.txt
(除非命令可能比print
更神秘,目录分隔符可能是一些疯狂的东西,如方括号和冒号,或其他;
lpr [mine:studies:2021:spring_semester]term_paper.txt
但对于这篇文章来说并不重要)如果你想复制这个文件,你将不得不两次拼写整个内容:
copy mine/studies/2021/spring_semester/term_paper.txt mine/studies/2021/spring_semester/term_paper.backup
接着提出了当前工作目录的概念。假设你可以说:“从现在开始,直到我另外说明,所有我所说的文件都位于这个特定的目录中。” 因此,cd
命令诞生了(除了一些旧系统,如VMS,它被称为更加笨重的名称,例如SET DEFAULT
)。
cd mine/studies/2021/spring_semester
print term_paper.txt
copy term_paper.txt term_paper.backup
这就是全部。当你使用
cd
(或在Python中使用
os.chdir()
)时,你会改变当前的工作目录。它会一直保留,直到你退出登录(或以其他方式退出这个进程),或者直到你通过
cd
切换到另一个工作目录,或者切换到另一个进程或窗口,在那里你正在运行一个具有自己独立当前工作目录的单独命令。就像你可以在不同目录下打开多个文件浏览器窗口(资源管理器、Finder或Nautilus或无论它被称为什么)一样,你也可以打开多个终端,每个终端都运行一个具有自己独立当前工作目录的shell。
因此,当你在终端中键入
pwd
(或
cwd
或者在你的命令语言中被称为什么的命令)时,结果几乎取决于你之前在该窗口或进程中所做的操作,可能还取决于你如何创建该窗口或进程。在许多类Unix系统上,当你使用关联的shell进程创建一个新的终端窗口时,它最初是在你的主目录(
/home/you
在许多Unix系统上,在Mac上是
/Users/you
,在最近的Windows上是类似于
C:\Users\you
的东西)中打开的,尽管可能可以配置你的终端在其他地方打开 (常见的是在某些表面上“现代”和“友好”的系统中,在你的主目录下的
Desktop
或
Documents
中)。
许多初学者对运行程序发生的情况模糊不清,心中没有完整的概念。许多人会不断地
cd
到包含他们的脚本或程序的任何目录中,并且当你告诉他们不需要这样做时,他们会真正感到害怕和困惑。如果
frobozz
在
/home/you/bin
中,那么你就不必这样做。
cd /home/you/bin
./frobozz
因为您可以直接运行它
/home/you/bin/frobozz
如果ls
在/bin
中,同样地你绝对不需要
cd /bin
./ls
仅仅获取一个目录列表。
此外,就像ls
(或在Windows上为dir
)的例子应该让你信服的那样,你运行的任何程序都将在您的当前目录中寻找文件。不是程序或脚本保存的目录。因为如果是这样的话,ls
只能生成它所在的目录(/bin
)的列表 - 目录列表程序、复制程序或者文字处理程序没有任何特殊之处;它们都按设计在当前工作目录中查找(尽管有些GUI程序会以您的Documents
目录作为它们的当前工作目录启动,至少如果您没有告诉它们不这么做的话)。
许多初学者编写的脚本要求输入和输出文件位于特定用户主目录内的特定目录中,但这只是差劲的设计; 一个良好编写的程序将简单地在当前工作目录中查找其输入文件,除非另有指示,并将输出写入当前目录(或者如果输出由多个文件组成,则在当前目录中创建一个新目录)。
然后,Python与任何其他程序没有区别。如果在运行python
时您的当前工作目录为/Users/you/Documents
,则该目录是您的Python脚本或解释器中的os.getcwd()
产生的结果(除非在运行时单独使用os.chdir()
进入不同的目录;但同样,这可能是不必要的,通常表明脚本是由初学者编写的)。如果您的Python脚本接受一个文件名参数,则它可能应该仅仅让操作系统打开
用户传递的任何东西,这意味着相对文件名是相对于调用用户的当前工作目录的。
python /home/you/bin/script.py file.txt
如果在当前目录下不存在file.txt
文件,那么应该简单地使用open(sys.argv[1])
并因错误而失败。让我们再说一遍; 它不会在/home/you/bin
中查找file.txt
- 除非这也是您,调用用户的当前工作目录,在这种情况下,您当然可以简单地编写
python script.py file.txt
顺便提一下,许多初学者不必要地尝试像这样做:
with open(os.path.join(os.getcwd(), "input.txt")) as data:
...
这段代码多余地调用了os.getcwd()
。为什么是多余的呢?如果您一直在跟进,那么您已经知道答案了:操作系统会在当前工作目录中查找相对文件名(如此处的input.txt
)。因此,您只需要:
with open("input.txt") as data:
...
最后一点说明。 在类Unix系统中,所有文件最终都在根目录 /
中,其中包含许多其他目录(通常普通用户不被允许在那里写任何内容,并且通常拥有执行此操作特权的系统管理员也不希望这样做)。 通过从根目录到当前目录跟踪路径,可以将每个相对文件名转换为绝对文件名。 因此,如果我们要访问的文件位于 /home/you/Documents/file.txt
中,则意味着 home
在根目录中,并包含 you
,它又包含 Documents
,它又包含 file.txt
。 如果您的当前工作目录是 /home
,则可以使用相对路径 you/Documents/file.txt
引用同一文件; 如果您的当前目录是 /home/you
,则其相对路径为 Documents/file.txt
(如果您的当前目录是 /home/you/Music
,您可以使用 ../Documents/file.txt
,但是现在让我们不再深入探讨这个例子)。
Windows 的排列略有不同,具有多个带有单字母标识符的驱动器,每个驱动器都有自己的根目录; 因此,C:驱动器的根目录是 C:\
,D:驱动器的根目录是 D:\
等(目录分隔符是反斜杠而不是斜杠,但几乎可以在任何地方使用斜杠代替它,这通常是为了保持您的理智)。
$ python
,那么Python将以CWD为/Users/apple/Documents
启动。 - decezeos.getcwd()
将会给出你正在执行它的目录名称。 - ggupta