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/
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
I know I can use subprocess
and run ln
command. I don't want that solution.
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
.
symlink() method in Python is used to create symbolic link. This method creates symbolic link pointing to source named destination.
Why use symbolic links? You can operate on symlinks as if they were the actual files to which they pointing somewhere down the line (except deleting them). This allows you to have multiple "access points" to a file, without having excess copies (that remain up to date, since they always access the same file).
Symbolic links can be made between different file systems, hard ones cannot. Hard links share the inode number, symbolic links do not. With symbolic links, if the original file or directory is deleted, the information is lost, with hard links it is not.
A hard link is a file all its own, and the file references or points to the exact spot on a hard drive where the Inode stores the data. A soft link isn't a separate file, it points to the name of the original file, rather than to a spot on the hard drive.
A symlink is a symbolic Linux/ UNIX link that points to another file or folder on your computer, or a connected file system. This is similar to a Windows shortcut. Symlinks can take two forms: Soft links are similar to shortcuts, and can point to another file or directory in any file system.
os.symlink
creates a single symlink.
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)))
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.
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)))
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."
The right answer is to use glob
, or fnmatch
, or os.listdir
plus a regex, or whatever you prefer.
Do not use os.walk
, because that does a recursive filesystem walk, so it's not even close to shell *
expansion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With