6

I have a directory, /original, that has hundreds of files. I have a script that will process files one at a time and delete the file so it's not executed again if the script gets interrupted. So, I need a bunch of soft links to the files on /original to /processing. Here's what I tried:

find /original -name "*.processme" -exec echo ln -s {} $(basename {}) \;

and got something like:

ln -s /original/1.processme /original/1.processme
ln -s /original/2.processme /original/2.processme
ln -s /original/3.processme /original/3.processme
...

I wanted something like:

ln -s /original/1.processme 1.processme
ln -s /original/2.processme 2.processme
ln -s /original/3.processme 3.processme
...

It appears that $(basename) is running before {} is converted. Is there a way to fix that? If not, how else could I reach my goal?

User1
  • 39,458
  • 69
  • 187
  • 265
  • `basename` is run only once; see for an explanation http://stackoverflow.com/questions/4793892/recursively-rename-files-using-find-and-sed/4794313#4794313 – Fred Foo Feb 01 '11 at 15:43

6 Answers6

16

You can also use cp (specifically the -s option, which creates symlinks), eg.

find /original -name "*.processme" -print0 | xargs -0 cp -s --target-directory=.
Hasturkun
  • 35,395
  • 6
  • 71
  • 104
  • This is the best recommendation at this time as using xargs instead of find with -exec is far more optimal. – etherfish Apr 11 '17 at 21:17
6

find /original -name '*.processme' -exec echo ln -s {} . \;

Special thanks to Ryan Oberoi for helping me realize that I can use a . instead of $(basename ...).

User1
  • 39,458
  • 69
  • 187
  • 265
  • Should be `'*.processme'` (single quotes) so that you do not match any files left over in the current directory. – mark4o Feb 01 '11 at 15:58
2

How about -

ln -s $(echo /original/*.processme) .
Ryan Oberoi
  • 13,817
  • 2
  • 24
  • 23
1

you simply need to remove echo and strip the repeat of the filepath and basename entirely

If your Source folder is this

ls -l /original
total 3
-rw-r--r-- 1 user user   345 Dec 17 21:17 1.processme
-rw-r--r-- 1 user user   345 Dec 17 21:17 2.processme
-rw-r--r-- 1 user user   345 Dec 17 21:17 3.processme

Then

cd /processing
find /original -name "*.processme" -exec ln -s '{}' \;

Should Produce

ls -l /processing
total 3
lrwxrwxrwx 1 user user 33 Dec 17 21:38 1.processme -> /original/1.processme
lrwxrwxrwx 1 user user 33 Dec 17 21:38 2.processme -> /original/2.processme
lrwxrwxrwx 1 user user 33 Dec 17 21:38 3.processme -> /original/3.processme

Aware the OP is from 5 years ago I post this for those seeking the same solution like myself before I worked it out.

1

Give this a try:

find /original -name "*.processme" -exec sh -c 'echo ln -s "$@" $(basename "$@")' _ {} \;
Dennis Williamson
  • 346,391
  • 90
  • 374
  • 439
0

ls /home/mindon/bin/* | xargs ln -s -t /usr/local/bin/

mindon
  • 318
  • 4
  • 13