A good[ish] website
Web development blog, loads of UI and JavaScript topics
This is a post about understanding linking, symbolic links and hard links.
Symlink, symbolic link, or soft link:
In computing, a symbolic link (also symlink or soft link) is a special type of file that contains a reference to another file or directory in the form of an absolute or relative path and that affects pathname resolution. —Wikipedia
Hard link:
In computing, a hard link is a directory entry that associates a name with a file on a file system. —Wikipedia
Symlink is kind of like having a directory, or a file, in two places at the same time.
If you execute a file in a path ./file-a it actually runs the in location ./file-b.
Hard link syntax:
┌──The link command
│
│                          ┌──Path to the intended link, can use . or ~
│                          │
│                    ┌─────┴──────┐
ln /path/to/original /path/to/link
    └───────┬───────┘
            └──Path to the original file/folder can
               use . or ~ or other relative pathsSymlink:
┌──The link command
│   ┌──Create a symbolic link
│   │                         ┌── Path to the intended symlink, can use . or ~
│   │                         │
│   │                   ┌─────┴────────┐
ln -s /path/to/original /path/to/symlink
        └───────┬───────┘
                └── the path to the original file/folder
                    can use . or ~ or other relative pathsLike the name suggest, soft link is more "fragile" than a hard link.
Here’s stuff one can do with hard links that would break a soft link:
Stuff that soft links do that hard links can’t:
Maybe there’s more that I just don’t know, drop a comment if you have something to add.
There are these things called inodes (Index Nodes) inside your computer, which represent files and directories.
An inode is a data structure on a traditional Unix-style file system such as UFS or ext3. An inode stores basic information about a regular file, directory, or other file system object.
A file is really a link to an inode, hard link creates another file with a link to the same inode.
If you want to test this in practice, you can quickly make some test files with dummy content:
$ mkdir link-test \
  && cd link-test \
  && echo Banana > File_A \
  && echo Apple > File_B \
  && echo Orange > File_C \
  && mkdir Dir_A \
  && mv File_C Dir_A/File_CThat gives you:
├── Dir_A
│   └── File_C
├── File_A
└── File_BYou may see the inode number of File_A:
$ ls -i File_A
51882811 File_AThe stat command shows all the attributes stored into the inode:
$ stat -x File_A
    File: "File_A"
    Size: 7            FileType: Regular File
    Mode: (0644/-rw-r--r--)         Uid: (  501/   bob)  Gid: (   20/   staff)
Device: 1,4   Inode: 51882811    Links: 1Access: Tue Jan 20 09:14:04 2015
Modify: Tue Jan 20 09:14:04 2015
Change: Tue Jan 20 09:14:04 2015This is on OS X, the output of stat might look a bit different on other systems.
👉 Related: Better stat command.
Files can be deleted based on their inode number:
$ find . -inum 51882811 -exec rm -i {} ;In hard links the link sits, kind of, between the inode and the file:
$ ln File_A File_B
┌──────────┐     ┌──────────┐
│  File_A  |     |  File_B  |
└─────┬────┘     └─────┬────┘
      |                |
      └─────┐  ┌─link──┘
            |  |
      ┌─────┴──┴─────┐
      |    inode     |
      | representing |
      |    File_A    |
      └──────────────┘Where as soft link has nothing to do with the inode, it links between the files like so:
$ ln -s File_A File_B
  ┌──────────┐          ┌──────────┐
  |  File_A  ├───link───|  File_B  |
  └─────┬────┘          └──────────┘
        |
        └─────┐
              |
        ┌─────┴────────┐
        |    inode     |
        | representing |
        |    File_A    |
        └──────────────┘Hope I got that right, please correct me in the comments if you have a better explanation.
If link target file name is not specified, the originals name will be used:
$ cd link-test
$ ln -s /path/to/File_B .That just grabs the File_B from an absolute path and jugs the link into the current directory.
Any sort of a relative path can be used with links if needed:
$ ln -s ../../File_B .The test directory has one soft link and one hard link. The -l flag on the ls command shows the symlink locations:
$ ls -l
-rw-r--r--  1 bob  staff  7 20 Jan 09:14 File_A
lrwxr-xr-x  1 bob  staff  6 21 Jan 10:32 File_A_link -> File_A-rw-r--r--  2 bob  staff  6 20 Jan 09:14 File_B
-rw-r--r--  2 bob  staff  6 20 Jan 09:14 File_B_linkOr the more explicit command readlink can be used:
$ readlink File_A_link
File_AHard links aren’t shown the same way, per se. But notice the number 2 before the user name on the ls command output (line highlighted):
$ ls -l
-rw-r--r--  1 bob  staff  7 20 Jan 09:14 File_A
lrwxr-xr-x  1 bob  staff  6 21 Jan 10:32 File_A_link -> File_A
-rw-r--r--  2 bob  staff  6 20 Jan 09:14 File_B-rw-r--r--  2 bob  staff  6 20 Jan 09:14 File_B_link            ^That means the file has two names, the original and the link. The duplicate files can be viewed with find:
$ find . -xdev -samefile File_B
./File_B
./File_B_linkHere’s the breakdown of the command:
.-xdev-samefile filename-L is specified, it is also true if the file is a symbolic link and points to a name.File_B$ rm File_B
$ ls
File_A    File_A_link    File_B_linkThe File_B_link persists, essentially it’s now the original File_B.
Either, remove the link:
$ rm File_A_linkOr use unlink:
$ unlink File_A_linkThere is a small gotcha here, link the directory and try to remove it, and bash will nag you about it:
$ ln -s Dir_A Dir_A_link
$ unlink Dir_A_link/
unlink: Dir_A_link/: is a directoryThe gotcha being the forward slash after the directory name, leave out and it should work:
$ unlink Dir_A_linkNow the File_A_link links to File_A:
$ ls -l File_A_link
lrwxr-xr-x  1 bob  staff  6 21 Jan 15:09 File_A_link -> File_AUpdate the link to point to Dir_A/File_C:
$ ln -nsf Dir_A/File_C File_A_linkSymlink can be tested with an if statement. The syntax is:
[ -h FILE ] True if FILE exists and is a symbolic link.
Simple example script:
is_link() {
  local file=$1
  [[ -h $file ]]
}
if is_link path/to/file; then
  # Do something...
fiThat’s the basics of links, thanks for reading. Please leave a comment if you have something to add.
Comments would go here, but the commenting system isn’t ready yet, sorry.