Can I brew link only files without conflicts?

Viewed 114

Is there a way to brew link just those files without conflicts?

As near as I can tell, the only options are to force an overwrite of all conflicting roles, or to link no files at all. For example I have an existing compare that I need to keep, but need ImageMagick's convert. When I brew install imagemagick I get

Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/compare
Target /usr/local/bin/compare
already exists. You may want to remove it:
  rm '/usr/local/bin/compare'

To force the link and overwrite all conflicting files:
  brew link --overwrite imagemagick

To list all files that would be deleted:
  brew link --overwrite --dry-run imagemagick

Possible conflicting files are:
/usr/local/bin/compare -> /Applications/Araxis Merge.app/Contents/Utilities/compare

But the only way offered to proceed is either to leave all of ImageMagick unlinked, or to overwrite my existing compare.

How do I brew link everything but the existing compare? Is there a way to install only convert perhaps?

1 Answers

Here's a shell function I wrote to do this (for the zsh that's now standard on macOS, but it will run on Bash with small adjustments 1):

local targetdir
targetdir=($(brew --cellar $1)/*/bin) || return
local linksdir=$(brew --repo)/bin

for ex in "$targetdir"/*(^/)        # files (and symlinks), not subdirectories
do
    local exname=${ex##*/}
    if builtin which "$exname" &>/dev/null
    then
        echo "  $exname already available in the path - skipped"
    else
        ln -s "$ex" "$linksdir/" && echo "$exname linked from $linksdir"
    fi
done

I saved it as a shell function called blink and when I call it with a package name, like

blink binutils

it symlinks only the binaries whose names aren't already available in the $PATH.

1The adjustments to make it work on Bash: remove the final (^/) form the for ex... line, and the builtin 3 lines further down.

Related