Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to use find to create a bunch of symlinks but using the result with {} includes ./ before each filename. How can I avoid that?

find . -type l -name '*.h' -exec ln -s /sourcedir/{} /destinationdir/{} \;
share|improve this question
Is your find supporting the -printf option? – manatwork Apr 12 '13 at 11:35
yes i think it does – Mark Robinson Apr 12 '13 at 11:38
See the find . -type l -name '*.h' -printf 'ln -s /sourcedir/%f /destinationdir/%f\n''s output. If you like it, pipe it to sh. Of course, special characters in the file names will be a problem. – manatwork Apr 12 '13 at 11:41
@manatwork I think you have the best answer there. If you post it as an answer I'll mark it as accepted – Mark Robinson Apr 12 '13 at 11:56
@manatwork, ITYW %P instead of %f here. – Stéphane Chazelas Apr 12 '13 at 12:16

Use the standard syntax, like:

S=/sourcedir D=/destdir find . -type l -name '*.h' -exec sh -c '
  for i do
    ln -s -- "$S${i#.}" "$D/$i"
  done' sh {} +

If you want to use GNUisms, you could do:

find . -type l -name '*.h' -printf '/sourcedir/%P\0/destdir/%P\0' |
  xargs -r0n2 ln -s

Or if /sourcedir is the current directory:

find "$PWD" -type l -name '*.h' -printf '%p\0/destdir/%P\0' |
  xargs -r0n2 ln -s
share|improve this answer

You only have to change one character in your command:

find * -type l -name '*.h' -exec ln -s /sourcedir/{} /destinationdir/{} \;
#    ^
share|improve this answer
Good point, but it should be noted though that it would fail if any file is named !, ( or ) or anything starting with a - in the current directory. It will also skip the hidden files and dirs in the current directory. – Stéphane Chazelas Apr 12 '13 at 13:07
@StephaneChazelas You are right. I had thought about the hidden files and dirs myself but found only one such file in the 75K .h on my systems (ubuntu Linux). – Anthon Apr 12 '13 at 13:17

find will print names relative to the paths you provide as arguments. In this case, the path is ., so all the names will begin with ./. To get absolute paths, you need to provide an absolute path as input:

find "$PWD" -type l -name '*.h'

This command uses the $PWD environment variable, which contains the absolute path of the current working directory, so it should preserve the meaning of your original command.

share|improve this answer
He would then need to strip that $PWD off the destination of the ln command. – Stéphane Chazelas Apr 12 '13 at 11:44
good point. Also I think I was answering a question he didn't ask. :( – bonsaiviking Apr 12 '13 at 11:45

Your Answer


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.