一尘不染

`os.symlink`与`ln -s`

linux

我需要为dir2中的dir1(文件或目录)的每个项目创建一个符号链接。dir2已经存在,并且不是符号链接。在Bash中,我可以通过以下方式轻松实现此目标:

ln -s /home/guest/dir1/* /home/guest/dir2/

但是在使用python时os.symlink出现错误:

>>> os.symlink('/home/guest/dir1/*', '/home/guest/dir2/')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 17] File exist

我知道我可以使用subprocess并运行ln命令。我不想要那个解决方案。

我也知道可以使用os.walk或解决方法glob.glob,但是我想知道是否可以使用os.symlink


阅读 333

收藏
2020-06-07

共1个答案

一尘不染

os.symlink 创建一个符号链接。

ln -s创建多个符号链接(如果它的最后一个参数是目录,并且有多个源)。Python等效项如下所示:

dst = args[-1]
for src in args[:-1]:
    os.symlink(src, os.path.join(dst, os.path.dirname(src)))

那么,当您这样做时它如何工作ln -s /home/guest/dir1/* /home/guest/dir2/?您的 外壳
通过将通配符转换为多个参数来实现此目的。如果你是刚刚execln命令使用通配符,它会寻找一个单一来源字面上命名*/home/guest/dir1/,在该目录中没有的所有文件。

Python等效项是这样的(如果您不介意将两个级别混合在一起,而忽略了许多其他情况,例如shell可能出现的波浪号,env变量,命令替换等):

dst = args[-1]
for srcglob in args[:-1]:
    for src in glob.glob(srcglob):
        os.symlink(src, os.path.join(dst, os.path.dirname(src)))

您不能os.symlink仅凭它的一部分来做到这一点,因为它不能做到这一点。这就像在说:“我想做的事情等同于find . -name foo使用os.walk而不过滤名称”。或者,就这一点而言,我想做的事情就等于ln -s /home/guest/dir1/* /home/guest/dir2/不让我的外壳出现问题。”

正确的答案是使用glob,或者fnmatch,或者os.listdir加上一个正则表达式,或任何你喜欢的。

千万 不能 使用os.walk,因为做了 递归 文件系统的步行路程,所以它甚至还没有接近外壳*扩展。

2020-06-07