Search code examples
bashmacossh

How to get readlink -e on M1 Macs which also works when used in bash scripts?


I am using several bash scripts for build and deployment processes which use readlink with the -e option. Since this option is not available I followed this suggest to install coreutils and create a symbolink between greadlink and readlink. This worked perfectly on my Intel mac but when I recently switch to M1 mac I realized that the path to greadlink and readlink are changed so I tried this:

ln -s /opt/homebrew/bin/greadlink /usr/bin/readlink

Which gave me an error: Operation not permitted

I realised that this is because of the System Integrity Protection

How can I still use readlink -e in my bash scripts without deactivate the System Integrity Protection?


Solution

  • One approach is to create a script named readlink somewhere in your PATH with the following content.

    #!/bin/sh
    
    exec greadlink "$@"
    

    • Just make sure that the relative path of script named readlink comes before /usr/bin/ since the system readlink is in /usr/bin when you run:
    declare -p PATH
    

    or

    echo "$PATH"
    

    An example how to do it:

    Create a directory in ~/, name it scripts since it will have script as contents.

    mkdir -p ~/scripts
    

    Edit ~/.bashrc to include the created directory in the PATH env variable.

    if [[ :$PATH: != *:$HOME/scripts:* ]]; then
      PATH=$HOME/scripts:$PATH
    fi
    

    Source ~/.bashrc

    source ~/.bashrc
    

    Create a script name readlink inside the ~/scripts directory with the following contents:

    #!/bin/sh
    
    exec /opt/homebrew/bin/greadlink "$@"
    

    Make it executable

    chmod +x ~/scripts/readlink
    

    Check which readlink is the first in PATH

    type -a readlink
    

    Output should be something like.

    readlink is /home/zlZimon/scripts/readlink
    readlink is /usr/bin/readlink
    

    • Note that the current work around is for a single user, or rather the user that has scripts directory in PATH, for a system wide approach one can use the path from homebrew or /usr/local/ or whichever default is available for all users.