Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I can show the target file that a link points to using ls -l:

snowch$ ls -l /usr/local/bin/mvn
lrwxr-xr-x  1 snowch  admin  29 12 Dec 08:58 /usr/local/bin/mvn -> ../Cellar/maven/3.2.3/bin/mvn

Is there a way to show less output without having to pipe through another command such as awk? E.g:

snowch$ ls ?? /usr/local/bin/mvn
/usr/local/bin/mvn -> ../Cellar/maven/3.2.3/bin/mvn

I'm running 3.2.53 on OS X 10.9.5. The output from several commands is shown below:

snowch$ ls -H /usr/local/bin/mvn
/usr/local/bin/mvn

snowch$ ls -L /usr/local/bin/mvn
/usr/local/bin/mvn

snowch$ file /usr/local/bin/mvn
/usr/local/bin/mvn: POSIX shell script text executable

snowch$ file -b /usr/local/bin/mvn
POSIX shell script text executable
share|improve this question

3 Answers 3

up vote 3 down vote accepted

ls unfortunately doesn't have an option to retrieve file attributes and display them in an arbitrary way. Some systems have separate commands for that (for instance GNU has a stat command or the functionality in GNU find).

On most modern systems, with most files, this should work though:

$ ln -s '/foo/bar -> baz' the-file
$ LC_ALL=C ls -ldn the-file | sed '
   1s/^\([^[:blank:]]\{1,\}[[:blank:]]\{1,\}\)\{8\}//'
the-file -> /foo/bar -> baz

That works by removing the first 8 blank delimited fields of the first line of the output of ls -l. That should work except on systems where the gid is not displayed there or the first 2 fields are joined together when there's a large number of links.

With GNU stat:

$ LC_ALL=C stat -c '%N' the-file
'the-file' -> '/foo/bar -> baz'

With GNU find:

$ find the-file -prune \( -type l -printf '%p -> %l\n' -o -printf '%p\n' \)
the-file -> /foo/bar -> baz

With FreeBSD/OS/X stat:

f=the-file
if [ -L "$f" ]; then
  stat -f "%N -> %Y" -- "$f"
else
  printf '%s\n' "$f"
fi

With zsh stat:

zmodload zsh/stat
f=the-file
zstat -LH s -- "$f"
printf '%s\n' ${s[link]:-$f}

Many systems also have a readlink command to specifically get the target of a link:

f=the-file
if [ -L "$f" ]; then
  printf '%s -> ' "$f"
  readlink -- "$f"
else
  printf '%s\n' "$f"
fi
share|improve this answer
    
stat -f "%N -> %Y" -- /usr/local/bin/mvn worked great. Thanks! –  SHC Dec 12 '14 at 10:51

Use the file command.

[sreeraj@server ~]$ ls -l mytest
lrwxrwxrwx 1 sreeraj sreeraj 15 Dec 12 09:31 mytest -> /usr/sbin/httpd

[sreeraj@server ~]$ file mytest
mytest: symbolic link to `/usr/sbin/httpd'

or

[sreeraj@server ~]$ file -b mytest
symbolic link to `/usr/sbin/httpd'
[sreeraj@server ~]$

Also, please go read through man page of ls and check the options -L and -H and see if that would suffice your requirement.

share|improve this answer
    
cool, learn something new every day. –  rob Dec 12 '14 at 9:59
    
@Sree - Many thanks! I had tried the ls options, but not file. Unfortunately, neither seems to work :( –  SHC Dec 12 '14 at 10:04
    
@SHC Sorry, I assumed that you are on a linux box. Please add osx as one of your tags. That should get to the attention of osx users as well. I have edited the post to add the tag, but I don't have enough credits for the edit to appear immediately. –  Sree Dec 12 '14 at 10:08
    
@Sree - no worries, and sorry for the confusion. I've upvoted your answer anyway as it will be useful when I'm back on a linux machine. –  SHC Dec 12 '14 at 10:10
    
maybe check 'readlink' utility on osx. –  tonioc Dec 12 '14 at 10:35

With a GNU ls at least (and, apparently, tcsh's implementation) you can hack the $LS_COLORS environment variable to insert delimiters where you like (but tcsh's builtin ls-F doesn't do link targets - only link flags) Usually ls inserts arbitrary non-printable terminal escapes based on the values stored within that environment var, but there's nothing stopping us from inserting arbitrary anything else instead. More on this here.

For example:

LS_COLORS='ln=///\n:lc=:no=//:rc=:rs=:' \
\ls ~ -l --color=always | 
sed '\|///|,\|//|!d;//d'

That puts a string like // at the head of every listing (so just before lrwcrwx) and a ///\n just before the filename of any link. sed then filters on line ranges - it will delete every input line until it encounters /// and from there through the next line which matches // it will delete lines matching //. So it only gets the link name and link target - regardless of intervening characters. This is because / can't occur in a filename - and those in any path ls might print will only occur singly.

See?

mkdir test; cd test
touch 'long


name' shortname
ln -s l* "$(printf %s.ln l*)"; ln -s s* shortname.ln

LS_COLORS='ln=///\n:lc=:no=//:rc=:rs=:' \
\ls  -l --color=always | sed '\|///|,\|//|!d;//d'

...which prints:

long


name.ln -> long


name
shortname.ln -> shortname

Try it yourself.

share|improve this answer
    
Do you know of any implementation besides modern versions of GNU ls that supports LS_COLORS that way and a --color=always and options after arguments? If on a GNU system, why would you use something that convoluted when you can use find or stat? That also probably won't work if you do some ln -s /// some-file. –  Stéphane Chazelas Dec 12 '14 at 11:48
    
@StephaneChezales - this indicates at least that it should work similarly with a bsd ls. I remember reading that somewhere else months ago about lss all tending to accept a termcap like syntax. Good point about the ln -s /// thing - but \0NULs work as well - and -Recursively. As to why - well, it's easy to use. In some cases easier than find - and it seemed a little more on topic here than find would have been. In any case, not too many people consider it, so I mention it when I'm reminded. –  mikeserv Dec 12 '14 at 11:57
    
See the man page or there for FreeBSD. If you want to test things on FreeBSD, you can use live CDs like GhostBSD/mfsbsd in a VM. –  Stéphane Chazelas Dec 12 '14 at 12:09
    
@StéphaneChazelas - no, i dont need to test it - definitely a wholly different animal. If you care to look, the gnu source is also linked to in the link in this answer. i wonder where i read that other thing? thanks very much for pointing that out though, that was a mistaken assumption im happy to discard. ive edited the answer. –  mikeserv Dec 12 '14 at 12:29
    
recent versions of tcsh have a ls-F builtin that supports LS_COLORS the same way as some versions of GNU ls, but it resorts to invoking ls -F if you pass any option to it, so that won't work here unless ls is GNU ls on your system. –  Stéphane Chazelas Dec 12 '14 at 13:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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