Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I am keeping my dotfiles under version control and the script deploying them creates hard links. I also use etckeeper to put my /etc under version control. Recently I have gotten warnings like this:

warning: hard-linked files could cause problems with bzr

A simple copy (cp filename.ext filename.ext) will not work:

cp: `filename.ext' and `filename.ext' are the same file

Renaming/moving a file - except across volumes - also doesn't break the hard-link.

So my question is: is there a way to break a hard-link to a file without actually having to know where the other hard-link/s to that file is/are?

share|improve this question
1  
The "rm" command breaks hard links. –  Johan Mar 4 '13 at 12:53
add comment

4 Answers 4

up vote 5 down vote accepted

You probably mean that you want to split the hard-link off to a separate, independent file.

mv hardlink tempname && cp tempname hardlink && rm tempname

A hardlink is the connection between an entry in the directory and the inode block on the disk.

inodes store file meta-data, and for small files, some file systems stores data in the inode, otherwise pointers to the data blocks, and for very large files indirect and double-indirect lists of pointers to disk allocation units.

Regardless, the connection between the file name (Which is what the ls command produce) and the inode block which stores this meta-data, is called a hard link.

Having multiple hard links to a single file means the same inode referenced by more than one directory entry, possibly in different directories (on a single file system)

rm deletes the file name entry from the directory. Once an inode is no longer referenced by any files, its space is freed up for use by other files.

share|improve this answer
    
Indeed. This is what the cp and mv examples implied. So no way around using a temporary file, I see. –  0xC0000022L Mar 4 '13 at 13:20
    
@0xC0000022L, No, inodes don't contain pointers to other inodes. Just to data blocks (or they can double as data space if the object is small). –  vonbrand Mar 4 '13 at 13:26
3  
Make sure the permissions and other data is preserved when copying, i .e. use cp -a (at least GNU coreutils). –  vonbrand Mar 4 '13 at 13:29
    
@0xC0000022L, if you look carefully, there is just a temporary name for the orginal file, a new file is created only in the last step. –  vonbrand Mar 4 '13 at 13:32
    
@vonbrand They can indeed, depending on what file system is being used. –  Johan Mar 4 '13 at 13:35
show 5 more comments
cp -p filename filename.tmp
mv -f filename.tmp filename

Making it scriptable:

dir=$(dirname -- "$filename")
tmp=$(TMPDIR=$dir mktemp)
cp -p -- "$filename" "$tmp"
mv -f -- "$tmp" "$filename"

Doing the copy first, then moving it into place, has the advantage that the file atomically changes from being a hard link to being a separate copy (there is no point in time where filename is partial or missing).

share|improve this answer
    
Makes sense. +1 ... good thinking about the --, too –  0xC0000022L Mar 6 '13 at 0:49
add comment

The command you're looking for is unlink

share|improve this answer
    
Perhaps my question was not clear, but by "in-place" and the examples with cp and mv I meant to make clear that I wish the file to exist afterward. –  0xC0000022L Mar 4 '13 at 13:21
    
Ah, I didn't find that clear, no. You should go with Johan's answer, then. –  Jenny D Mar 4 '13 at 13:23
add comment

Put this at the end of your ~/.bashrc file.

delink () { tmpfile="$1$(date)"; cp -a "$1" "$tmpfile"; mv "$tmpfile" "$1"; }

Run it like this

delink filename
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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