3

It is easy to convert a symlink into a hardlink with ln -f (example)

It would also be easy to convert a hardlink (filenames link and original) back to a symbolic link to link->original in the case where you know both files and define yourself which one is the "original file". You could easily create a simple script convert-known-hardlink-to-symlink that would result in something like:

convert-known-hardlink-to-symlink link original
$ ls -li
3802465 lrwxrwxrwx 1 14 Dec  6 09:52 link -> original
3802269 -rw-rw-r-- 1  0 Dec  6 09:52 original

But it would be really useful if you had a script where you could define a working directory (default ./) and a search-directory where to search (default /) for files with the same inode and then convert all those hard-links to symbolic-links.

The result would be that in the defined working directory all files that are hard-links are replaced with symbolic-links to the first found file with the same inode instead.


A start would be find . -type f -links +1 -printf "%i: %p (%n)\n"

  • I'm not sure about this but i guess its impossible without checking EVERY file on your disk since hardlinks usually don't know, which are the other file(-names) which point to the same area on your harddisk. – tkausl Dec 6 '14 at 9:10
4

I created a script that will do this. The script converts all hard-links it finds in a source directory (first argument) that are the same as in the working directory (optional second argument) into symbolic links:

https://gist.github.com/rubo77/7a9a83695a28412abbcd

It has an option -n for a dry-run, that doesn't do anything but shows what would be done.

Main part:

$WORKING_DIR=./
#relative source directory from working directory:
$SOURCE_DIR=../otherdir/with/hard-links/with-the-same-inodes

# find all files in WORKING_DIR
cd "$WORKING_DIR"
find "." -type f -links +1 -printf "%i %p\n" | \
  while read working_inode working_on
do
    find "$SOURCE_DIR" -type f -links +1 -printf "%i %p\n" | sort -nk1 | \
      while read inode file
    do
        if [[ $inode == $working_inode ]]; then
            ln -vsf "$file" "$working_on"
        fi
    done
done

The -links +1 --> Will find all files that have MORE than 1 link. Hardlinked files have a link count of at least two.

1

At least GNU find also lets you search by Inode, either numerical (-inode) or by specifying the link (-samefile).

So you could use:

find "$WORKING_DIR" -type f -links +1 | while read file
do
  find "$SOURCE_DIR" -samefile "$file" -exec ln -vsf '{}' "$file" \;
done

You just have to make sure to use separate directories. On the other hand, ln would complain if you tried to link a file into itself.

Also, you should either provide an absolute path for $SOURCE_DIR, or use the -r option with ln to create relative links, otherwise the links may become broken.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.