How do I selectively create symbolic links to specific files in another directory in LINUX?
Asked Answered
S

4

4

I'm not exactly sure how to go about doing this, but I need to create symbolic links for certain files in one directory and place the symbolic links in another directory.

For instance, I want to link all files with the word "foo" in its name in the current directory bar1 that does not have the extension ".cc" and place the symbolic links in a directory bar2.

I was wondering if there was single line command that could accomplish this in LINUX bash.

Strenuous answered 4/6, 2012 at 20:45 Comment(1)
You should probably just write a simple shell script to do this.Zodiac
J
3

Assuming you are in a directory that contains directories bar1 and bar2:

find bar1 -name '*foo*' -not -type d -not -name '*.cc' -exec ln -s $PWD/'{}' bar2/ \;
Johanson answered 4/6, 2012 at 21:1 Comment(7)
I believe the requirement is to find files whose names contain foo and do not end in .cc (not files in a directory named foo).Tillett
You are right, I misread the question. I corrected my answer.Johanson
It shouldn't, but try the advice in the answer by @HaiWu (which is pretty much the same answer as this) and change add echo before ln so you can see exactly what command would run.Johanson
I think I'm going to combine the first part of this one with a forloop instead. Seem to be having a lot of difficulty with the -exec ln -s $PWD/'{}' bar2/ \; portion of the code.Strenuous
For some reason, the -exec ln -s $PWD/'{}' portion of the command is concatenating the full filesystem filename to itself again, resulting in broken links.Strenuous
Ahh figured out the problem...the first part of the command: find bar1 -name 'foo' -not -type d -not -name '*.cc' returns a list of the full filesystem filenames of the files to be symlinked...so in the second part where it says -exec ln -s $PWD/'{}' bar2/ \; it should really just be -exec ln -s '{}' bar2/ \;...but thanks a bunch for your help! I really appreciate it!Strenuous
I just looked this up: apparently when you give find an absolute path to search, it will return absolute paths. When given a relative path, it returns relative paths. So this is why my example worked for me.Johanson
T
2

Try this:

cd bar1
find . -maxdepth 1 -name '*foo*' -not -name '*.cc'  -exec echo ln -s $PWD/{} ../bar2 \;

Once you are satisfied with the dry run, remove echo from the command and run it for real.

Tetrastichous answered 4/6, 2012 at 21:4 Comment(0)
F
2

This is easily handled with extended globbing:

shopt -s extglob
cd bar2
ln -s ../bar1/foo!(*.cc) .

If you really want it all on one line, just use the command separator:

shopt -s extglob; cd bar2; ln -s ../bar1/foo!(*.cc) .

The two examples are identical, but the first is much easier to read.

Furie answered 4/6, 2012 at 21:6 Comment(0)
S
0

This technically doesn't count as a one line answer...but it can be pasted in a single instance and should do what you are looking for.

list=`ls | grep foo | grep -v .cc`;for file in $list;do ln $file /bar2/;done
Silverfish answered 4/6, 2012 at 21:0 Comment(3)
looks like the back ticks were left out around the variable "list", be sure to include them.Silverfish
Don't forget ln -s to create symbolic link as opposed to hard linksTetrastichous
This is made of winningNarrowminded

© 2022 - 2024 — McMap. All rights reserved.