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/{} \;
You only have to change one character in your command:
find * -type l -name '*.h' -exec ln -s /sourcedir/{} /destinationdir/{} \;
# ^
!, ( or ) or anything starting with a - in the current directory. It will also skip the hidden files and dirs in the current directory.
.h on my systems (ubuntu Linux).
find stuff in another directory (eg. find src/ -type l), is there a way to exclude src/ from the results?
cd src; find * -type l in that case.
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
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.
$PWD off the destination of the ln command.
find . -type l -name '*.h' -print0 | cut -z -c3- \
| xargs -0 -I '{}' ln -s '/sourcedir/{}' '/destinationdir/{}'
-print0 print the full file name on the standard output, followed by a null
character.man cut - remove sections from each line of files
-z line delimiter is NUL, not newline.-c select only these characters.N- from N'th byte, character or field, counted from 1, to end of line.man xargs - build and execute command lines from standard input.
xargs [options] [command [initial-arguments]]-0 Input items are terminated by a null character instead of by whitespace,
and the quotes and backslash are not special (every character is taken
literally).-I replace-str
Replace occurrences of replace-str in the initial-arguments with
names read from standard input. Also, unquoted blanks do not terminate
input items; instead the separator is the newline character.
Implies -L 1.-L max-lines
Use at most max-lines nonblank input lines per command line.
findsupporting the-printfoption?find . -type l -name '*.h' -printf 'ln -s /sourcedir/%f /destinationdir/%f\n''s output. If you like it, pipe it tosh. Of course, special characters in the file names will be a problem.%Pinstead of%fhere.find sourcedir -type l -name '*.h' -exec ln -s {} /destinationdir/{} \;... You would run the find command from the parent of /sourcedir, which is the root. On second thought that won't work because it will try to create a link called /destinationdir/sourcedir/file.h