1

I have this:

file_path="/actual/file/path"
read_link="$(readlink "$file_path")"  # just in case it's a symlink

readlink will echo an empty string if it's not a symlink? Is there an option to readlink that will just echo the original path if it's not a symlink?

roaima
  • 107,089
  • 14
  • 139
  • 261
Alexander Mills
  • 9,330
  • 19
  • 95
  • 180

3 Answers3

4

For a GNU/Linux system, the -f flag to readlink (--canonicalize), « canonicalize by following every symlink in every component of the given name recursively » will do this for you:

touch /tmp/real
ln -s /tmp/real /tmp/link

readlink -f /tmp/real    # → "/tmp/real"
readlink -f /tmp/link    # → "/tmp/real"

For a Mac OSX system, there is no option to do this, « If the given argument is not a symbolic link, readlink will print nothing and exit with an error ».

For both systems you can find the documentation and all available options for readlink with man readlink.

The closest you can get is to a general-purpose solution on OSX is something like this function

readlinkorreal() { readlink "$1" || echo "$1"; }

readlinkorreal /tmp/real    # → "/tmp/real"
readlinkorreal /tmp/link    # → "/tmp/real"
roaima
  • 107,089
  • 14
  • 139
  • 261
  • 1
    I didn't downvote, this works, if someone did downvote perhaps it's because they think the -m or -e option could work? I think your wrapper func makes sense – Alexander Mills Aug 06 '19 at 16:41
  • There is no `-m` or `e` option on the Mac. That's why I suggested the wrapper – roaima Nov 29 '21 at 08:49
1

Given the following file structure:

test/
├── link -> no-link
└── no-link

The -m option seems to do the trick.

florin@debian:/tmp/test$ readlink -m link 
/tmp/test/no-link
florin@debian:/tmp/test$ readlink -m no-link 
/tmp/test/no-link

1

readlink -f does this (as mentioned in @roaima’s answer).

macOS 12.3 has added support for this option, so you can now use it on Linux and macOS.

Frederik
  • 111
  • 2