`os.symlink`与`ln -s` [英] `os.symlink` vs `ln -s`

查看:224
本文介绍了`os.symlink`与`ln -s`的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to create a symlink for every item of dir1 (file or directory) inside dir2. dir2 already exists and is not a symlink. In Bash I can easily achieve this by:

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

但是在使用os.symlink的python中,我得到一个错误:

But in python using os.symlink I get an error:

>>> 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命令.我不想要那个解决方案.

I know I can use subprocess and run ln command. I don't want that solution.

我也知道可以使用os.walkglob.glob来解决,但我想知道是否可以使用os.symlink来实现.

I'm also aware that workarounds using os.walk or glob.glob are possible, but I want to know if it is possible to do this using os.symlink.

推荐答案

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

os.symlink creates a single symlink.

ln -s创建多个符号链接(如果其最后一个参数是目录,并且有多个源).等效的Python类似于:

ln -s creates multiple symlinks (if its last argument is a directory, and there's more than one source). The Python equivalent is something like:

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/时,它如何工作?您的 shell 通过将通配符转换为多个参数来实现这一目的.如果只用通配符exec ln命令,它将在/home/guest/dir1/中查找一个字面名为*的源,而不是该目录中的所有文件.

So, how does it work when you do ln -s /home/guest/dir1/* /home/guest/dir2/? Your shell makes that work, by turning the wildcard into multiple arguments. If you were to just exec the ln command with a wildcard, it would look for a single source literally named * in /home/guest/dir1/, not all files in that directory.

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

The Python equivalent is something like (if you don't mind mixing two levels together and ignoring a lot of other cases—tildes, env variables, command substitution, etc. that are possible at the shell):

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来做到这一点(它的一部分),因为它不能做到这一点.这就像说我想使用os.walk进行find . -name foo的等效操作而无需过滤名称".或者,就此而言,我想做与ln -s /home/guest/dir1/* /home/guest/dir2/等效的操作,而不会让我的外壳崩溃."

You can't do that with os.symlink alone—either part of it—because it doesn't do that. It's like saying "I want to do the equivalent of find . -name foo using os.walk without filtering on the name." Or, for that matter, I want to do the equivalent of ln -s /home/guest/dir1/* /home/guest/dir2/ without the shell globbing for me."

正确的答案是使用globfnmatchos.listdir加上正则表达式或您喜欢的任何内容.

The right answer is to use glob, or fnmatch, or os.listdir plus a regex, or whatever you prefer.

不要使用os.walk,因为这会执行递归文件系统,因此它甚至不接近shell *扩展.

Do not use os.walk, because that does a recursive filesystem walk, so it's not even close to shell * expansion.

这篇关于`os.symlink`与`ln -s`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆