I have an "install.sh" that installs my personal scripts:

find /home/Steven -name '*.sh' -exec ln -s -t /usr/local/bin {} +

I would like to make an "uninstall.sh" that removes the symbolic links created by "install.sh". I wrote this:

for z in /usr/local/bin/*
  if [ -h "$z" ]
  then rm "$z"

but it removes all symlinks, not just ones where the target is under "/home/Steven".

  • @StevePenny It occurred to me that there are a couple of minor possible ambiguities in the question related to symbolic links. The first is whether or not you're using absolute or relative paths when creating the symbolic links. The second is whether or not the targets of the symbolic links are links themselves. I suspect that neither of these will be issues in your specific case (as described in the question body), but it might be something to keep in mind. – igal Oct 28 '17 at 17:30
  • @igal you can see my command - so that answers at least one of the questions – Steven Penny Oct 28 '17 at 17:47
  • @StevePenny That's right. If you're only ever using absolute paths then that's not going to be an issue. – igal Oct 28 '17 at 17:50

If you have GNU or BSD find, this should do it:

find -lname '/home/Steven/*' -delete
  • @TavianBarnes This seems like a better solution. But this won't work if the symbolic links use relative paths, will it? – igal Oct 28 '17 at 17:21
  • 2
    @igal Right. That shouldn't be a problem in this specific case, because the links were created with absolute paths as seen in the question. In general it would be hard to use find to answer the question "does this symbolic link point somewhere under this directory?" – Tavian Barnes Oct 28 '17 at 17:36

You could modify your script and use grep and either readlink or realpath to extract the files in the desired subdirectory, e.g.:

for z in /usr/local/bin/*
  if [ -h "${z}" ] && readlink -f "${z}" | grep -q '^/home/Steven'
      then rm "${z}"

The readlink -f command returns the full path to the file pointed to by the symbolic link. The grep -q '^/home/Steven' command returns true if the path begins with the substring '/home/Steven' and returns false otherwise.

A word of caution: there is some ambiguity related to symbolic links that could affect the outcome here. The readlink -f command will resolve the link recursively, so the above command would fail if the file in the /home/Steven directory were itself a symbolic link point outside of this directory. If this isn't the desired behavior then you might want to use the realpath command instead.


To cover for the case where the links may be relative and to check that their canonical path is within /home/Steven, with zsh:

rm /usr/local/bin/*(@e{'[[ $REPLY:A = /home/Steven/* ]]'})


  • @ glob qualifier that matches on symlinks:
  • e{code} glob qualifier that matches based on the evaluation of the code (where $REPLY contains the path of the file to check)
  • $REPLY:A expands to the absolute path of $REPLY.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.