Take the 2-minute tour ×
Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

I'm looking for a single linux command that allows me to do the equivalent of this:

cp /some/path/file /another/path/ && ln -sf /another/path/file /some/path/

If there isn't one, what's the best way to do this for a bunch of files?

share|improve this question
    
I don't know Bash scripting well enough to write it, but my solution would be to just write a script and call it something catchy like cpln –  Unkwntech May 14 '09 at 8:33
    
Shouldn't cp be mv? –  Bart van Heukelom May 14 '09 at 8:41
    
No. The -f option to ln takes care of that. –  innaM May 14 '09 at 9:09
1  
try it on a 10GB file –  hayalci May 18 '09 at 18:49

3 Answers 3

up vote 5 down vote accepted

A small note, is that you could use ln both times to make the command not actually move the data (assuming both paths are on the same filesystem).

ln /some/path/file /another/path/ && ln -sf /another/path/file /some/path/

But I assume that you want to move the content of /some/path/ to an other disk, and then create links to the new files so "no one" notices.

for f in `ls /some/path/`; do ln /some/path/$f /another/path/ && ln -sf /another/path/$f /some/path; done

Wrapping it in a bash function:

function cpln {
    for f in `ls $1`
    do
        ln $1/$f $2 && ln -sf $2/$f $1
    done
}
share|improve this answer
    
Is there a way to make this work if what I'm moving happens to be a directory? –  tladuke Aug 9 '12 at 18:50
    
How does this move the actual file on disk? –  Ibrahim Dec 6 '12 at 10:55
    
Ibrahim: the data doesn't move, it just updates the pointers in the directory. –  Mr Shark Dec 10 '12 at 10:13
    
tladuke: Yes and no. Since the directory is much smaler on disk, there is no need for the ln trick (which don't work for directorys), just do a mv :-) –  Mr Shark Dec 10 '12 at 10:16

Seriously, I thought this was a really easy question.

Here's what I can do in perl:

#!/bin/perl
# Usage: cpln TARGETDIR SOURCE...
# Example: find tree/ -type f | xargs cpln commands/

$target = shift;

foreach(@ARGV) {
    m[(.*)/([^/]+)];
    system("cp $_ $target");
    system("ln -sf $target/$2 $1/");
}

I was hoping for something more elegant, but I guess I'll use that.

share|improve this answer
    
To do it "in Perl," you should use File::Copy (or similar) and symlink(). Perl is not shell; avoid system(), and especially avoid passing whole command lines to system() (e.g., what if an argument contains a space?). Either way, always, always, ALWAYS check return values. –  John Siracusa May 14 '09 at 14:53

Theres my script you could use (takes two parameters /some/path/file and /another/path/ ):

#!/bin/bash
cp $1 $2
if [ "$?" -ne "0" ]; then
    echo "Some error"
    exit 1
    fi
ln -sf $2/${1##*/} ${1%/*}
share|improve this answer
    
Cool trick with the string manipulations, never saw that before. Thanks! –  itsadok May 17 '09 at 11:17

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.