5

I am writing a bash shell script (for RH and Solaris) that uses openssl to create hash symlinks to certificates all within the same directory. I have approx 130 certificates and when new certs are added I would like the script to create symlinks for the new certs only. I may have to resort to deleting all symlinks and recreating them but if there is a not-so-difficult way to do this; that is preferable than deleting all and recreating.

I know how to find all files with symlinks:

find . -lname '*.cer'

or

find . -type l -printf '%p -> %l\n'

But I am not sure how to negate or find the inverse of this result in a for or other loop. I want to find all files in the current directory missing a symlink.

Thanks!

jww
  • 97,681
  • 90
  • 411
  • 885
Cito
  • 53
  • 1
  • 4
  • Find all files, find all files with symlinks, find the difference. – n. m. could be an AI Feb 28 '16 at 15:30
  • Loop through each file, checking if there is an associated link, if not, create the link. You also need to provide additional information like an example file name and an example link name to provide the correlation, if any, between them. That may also provide another way of identifying files needing links. – David C. Rankin Feb 28 '16 at 16:57
  • Possible duplicate of [How to check if symlink exists](http://stackoverflow.com/questions/5767062/how-to-check-if-symlink-exists). From the question and answers, it appears you want to test for both `-e` and `!-h` in Bash. – jww Feb 28 '16 at 19:30

2 Answers2

3
$ ls -srlt
example1.png
example.png -> ../example.png

$ find . -type f -print
./example1.png

$ find . ! -type f -print
.
./example.png
Andrea Corbellini
  • 17,339
  • 3
  • 53
  • 69
XaviOutside
  • 141
  • 4
2

Assuming GNU find (whose use I infer from your use of nonstandard action -printf), the following command will output the names of all files in the current directory that aren't the target of symlinks located in the same directory:

comm -23 <(find . -maxdepth 1 -type f -printf '%f\n' | sort) \
         <(find . -maxdepth 1 -lname '*' -printf '%l\n' | sort) 

Note: This assumes that the symlinks were defined with a mere filename as the target.
Also, GNU find doesn't sort the output, so explicit sort commands are needed.

You can process the resulting files in a shell loop to create the desired symlinks.

comm -23 <(find . -maxdepth 1 -type f -printf '%f\n' | sort) \
         <(find . -maxdepth 1 -lname '*' -printf '%l\n' | sort) |
  while IFS= read -r name; do ln -s "$name" "${name}l"; done

(In the above command, l is appended to the target filename to form the symlink name, as an example.)

mklement0
  • 382,024
  • 64
  • 607
  • 775