Why ln -sf does not overwrite existing link to directory
When you run:
ln -sf DIR2 L
This is creating a symlink inside DIR1 cause L points to DIR1 and ln dereferences it, creating L/DIR2 -> DIR1
.
The following:
rm -fr DIR1 DIR2 L
mkdir DIR1 DIR2
ln -v -s DIR1 L
ls -la L
ln -v -f -s DIR2 L
ls -la L
will output:
'L' -> 'DIR1'
lrwxrwxrwx 1 runner runner 4 Oct 21 18:13 L -> DIR1
'L/DIR2' -> 'DIR2'
lrwxrwxrwx 1 runner runner 4 Oct 21 18:13 L -> DIR1
To handle that, use the --no-dereference
option as indicated in answer in this thread on superuser.com.
ln -sf does not overwrite a symlink to a directory
man ln
SYNOPSIS
ln [OPTION]... [-T] TARGET LINK_NAME (1st form)
ln [OPTION]... TARGET (2nd form)
ln [OPTION]... TARGET... DIRECTORY (3rd form)
ln [OPTION]... -t DIRECTORY TARGET... (4th form)
DESCRIPTION
In the 1st form, create a link to TARGET with the name LINK_NAME.
In the 2nd form, create a link to TARGET in the current directory.
In the 3rd and 4th forms, create links to each TARGET in DIRECTORY.
You have the 3rd form, because your link is a link to a directory.
Atomic `ln -sf` in python (symlink overwriting exsting file)
This code tries to minimise the possibilities for race conditions:
import os
import tempfile
def symlink_force(target, link_name):
'''
Create a symbolic link link_name pointing to target.
Overwrites link_name if it exists.
'''
# os.replace() may fail if files are on different filesystems
link_dir = os.path.dirname(link_name)
while True:
temp_link_name = tempfile.mktemp(dir=link_dir)
try:
os.symlink(target, temp_link_name)
break
except FileExistsError:
pass
try:
os.replace(temp_link_name, link_name)
except OSError: # e.g. permission denied
os.remove(temp_link_name)
raise
Note:
If the function is interrupted (e.g. computer crashes), an additional random link to the target might exist.
An unlikely race condition still remains: the symlink created at the randomly-named
temp_link_name
could be modified by another process before replacinglink_name
.
I raised a python issue to highlight the issues of os.symlink()
requiring the target not exist.
Credit to Robert Seimer's input.
ln -s and overwriting a physical directory
The ln
utility may be asked to remove the destination if it already exists by adding the -f
option. However, the POSIX standard says that this is done with a call to the C library routine unlink()
, and about that function, the standard says
The
path
argument shall not name a directory unless the process has appropriate privileges and the implementation supports usingunlink()
on directories.
I have not access to a system where unlink()
is documented to remove directories, or where the -f
flag to ln
is documented to remove directories.
Your solution is therefore to either
$ rm -rf /path/to/A
or, which would be safer,
$ mv -f /path/to/A /path/to/A.orig
before creating the symbolic link.
Linux command for rmdir and mklink?
Well to answer
What is the rmdir and mklink command for linux platform ?
There is no
mklink
command available in Linux however an equivalent commandln
serves the purpose.Going By the man pages
rmdir
in Linux removes empty directories.
For windows it is - rmdir /S/Q for rmdir and mklink /D/J for mklink.
How to write similar in Linux ?
1. rmdir
- Removes a directory provided it's empty, However If directory is not empty then Using rm
is wise
Remove empty directory :
$ rmdir path/to/directory
Remove directories Recursively (useful for nested dirs) :
$ rmdir -p path/to/directory
Remove files from a location :
$ rm path/to/file path/to/another/file
Recursively remove a directory & all it's subdirectories :
$ rm -r path/to/directory
Force Remove a Directory, withour prompting for confirmation or showing any error messages :
$ rm -rf path/to/directory
Intercatively Remove multiple Files, with a prompt before every removal :
$ rm -i file another_file another_file
2. ln
- Creates links to files and folders
Create a hard link to file :
$ ln path/to/file/to/hardlink
Create a symbolic link to file of folder :
$ ln -s path/to/file/to/symlink
Overwrite an existing symbolic link to point to another file :
$ ln -sf path/to/new/file path/to/symlink
NOTE - You cannot use ln
to create hard links for directories.
Does symlink function in perl overwrite an existing link
symlink
simply calls the OS call by the same name (symlink(2)
), which returns error EEXIST
when "newpath
already exists".
If you wanted to implement -f
, you could use
unlink($new_qfn);
symlink($old_qfn, $new_qfn)
or die("Can't create symlink \"$new_qfn\": $!\n");
However, the following does a better job of handling race conditions:
if (!symlink($old_qfn, $new_qfn)) {
if ($!{EEXIST}) {
unlink($new_qfn)
or die("Can't remove \"$new_qfn\": $!\n");
symlink($old_qfn, $new_qfn)
or die("Can't create symlink \"$new_qfn\": $!\n");
} else {
die("Can't create symlink \"$new_qfn\": $!\n");
}
}
ln
uses the latter approach.
$ strace ln -sf a b
...
symlink("a", "b") = -1 EEXIST (File exists)
unlink("b") = 0
symlink("a", "b") = 0
...
Find circular symlinks with boost filesystem
You should be able to use boost::filesystem::canonical
or weakly_canonical
(in case the file need not exist).
Note that there can be performance overhead with many symlinks with many path elements, because path elements are stat
-ed, building a new path instance.
Live On Coliru
#include <boost/filesystem.hpp>
#include <iostream>
int main(int argc, char** argv) {
using namespace boost::filesystem;
for (path link : std::vector(argv+1, argv+argc)) {
boost::system::error_code ec;
auto target = canonical(link, ec);
if (ec) {
std::cerr << link << " -> " << ec.message() << "\n";
} else {
std::cout << link << " -> " << target << "\n";
}
if (ec) {
target = weakly_canonical(link, ec);
if (!ec) {
std::cerr << " -- weakly: -> " << target << "\n";
}
}
}
}
When creating a few symlinks of various quality:
ln -sf main.cpp a
ln -sf b b
ln -sf d c
Incoking it with a b c d
:
"a" -> "/tmp/1613746951-1110913523/main.cpp"
"b" -> Too many levels of symbolic links
"c" -> No such file or directory
-- weakly: -> "c"
"d" -> No such file or directory
-- weakly: -> "d"
ln command creates broken links
Some of the variations of ln
command are:
ln -s abs_path_to_link_target rel_path_from_current_dir_to_link_source
ln -s rel_path_from_link_src_to_target rel_path_from_current_dir_to_link_source
But the following, which you were trying to use, is not one of them:
ln -s rel_path_from_current_dir_to_link_target ...
Your makefile has another subtle error, namely, the link source, does not depend on the changes to the link target, it only depends on the existence of the link target.
And another problem, is that you have a "side effect", when you are making $(DLIB)
target. I am guessing you are a software eng, so you know that side effects are bad for parallelism, cause race conditions, and make code hard to read.
Also, one should always use automatic variables such as $@
, and depend everything on the Makefile.
Finally, I am hoping that you know why you are using -f
. Some of the responses above, including mine :), do not use it. It is very important in the Makefile context, don't drop it.
Bearing these points in mind, the cleanest and correct way to do this would be:
$(DLIB) $(DLIB).$(MAJOR): Makefile | $(DLIB).$(VERSION)
ln -sf $(abspath $|) $@
Related Topics
How to Get Around the Linux "Too Many Arguments" Limit
Is an Operating System Kernel an Interpeter for All Other Programs
Shuffle Output of Find with Fixed Seed
Linux Equivalent of Windows Dll Forwarders or MACos Reexport_Library
Cuda 5.0: Replacement for Cutil.H
How to Display Filename from a Column Using Awk
Segmentation-Fault Error Happening with Assembly Code Program
Killing Linux Process by Piping the Id
Why Would the Elf Header of a Shared Library Specify Linux as the Osabi
Using Gzip to Compress Files to Transfer with Aws Command
Django on Apache Wtih Mod_Wsgi (Linux) - 403 Forbidden
Determine Vm Size of Process Killed by Oom-Killer
Sed: Matching on 2 Patterns on the Same Line
Mathematical Expression Result Assigned to a Bash Variable
Write to Port 0Cf8H Fails with Segfault
How to Get the Offset in a Block Device of an Inode in a Deleted Partition