1

I like the --group-directories-first flag for ls. My .zshrc has this line in it:

alias ls="ls -h --color='auto' --group-directories-first"

The only thing I don't like is that symbolic links to directories don't get grouped with the directories.

Are there any switches I can add to the ls command that will cause symbolic-links-to-directories to group with directories? I'm disinclined to build a compound command, because I like being able to add additional switches to ls on the fly.

3

One option is to use the -L flag:

-L, --dereference

when showing file information for a symbolic link, show information for the file the link references rather than for the link itself

For example, assume I have the files and directories below:

$ ls -l --group-directories-first
total 0
drwxr-xr-x. 2 user group 6 Nov 30 08:19 zdir1
drwxr-xr-x. 2 user group 6 Nov 30 08:19 zdir2
-rw-r--r--. 1 user group 0 Nov 30 08:20 file1
-rw-r--r--. 1 user group 0 Nov 30 08:20 file2
lrwxrwxrwx. 1 user group 5 Nov 30 08:23 symlink -> zdir2

The symlink gets sorted with the directories when -L is used:

$ ls -lL --group-directories-first
total 0
drwxr-xr-x. 2 user group 6 Nov 30 08:19 symlink
drwxr-xr-x. 2 user group 6 Nov 30 08:19 zdir1
drwxr-xr-x. 2 user group 6 Nov 30 08:19 zdir2
-rw-r--r--. 1 user group 0 Nov 30 08:20 file1
-rw-r--r--. 1 user group 0 Nov 30 08:20 file2

As you noticed, ls no longer indicates whether the files are symlinks are not. I'm not familiar with a way in ls to show a symlink once it's been dereferenced, but I wrote a hacky bash function to do it for you:

lsd() {
        ls -lL --group-directories-first | while read line; do
                file=$(echo "$line" | awk '{print $NF}')
                ls -ld "$file" 2>/dev/null | grep -q "^l"
                if [ $? -eq 0 ]; then
                        symlink=$(ls -l $file | awk '{print $(NF-2),$(NF-1),$NF}')
                        echo "$line" | sed -e "s/^./l/" -e "s/$file/$symlink/"
                else
                        echo "$line"
                fi
        done
}

Essentially, the script will determine if the file output from ls -lL --group-directories-first is a symlink or not. If it is, the first character is changed to an l, and what the symlink points to is appended to the end of the line.

$ lsd
total 0
lrwxr-xr-x. 2 user group 6 Nov 30 13:49 symlink -> zdir2
drwxr-xr-x. 2 user group 6 Nov 30 13:49 zdir1
drwxr-xr-x. 2 user group 6 Nov 30 13:49 zdir2
-rw-r--r--. 1 user group 0 Nov 30 13:49 file1
-rw-r--r--. 1 user group 0 Nov 30 13:49 file2
  • What if the symbolic link is pointing to file? OP only wants links pointing to directories. – Prvt_Yadav Nov 30 '18 at 15:56
  • 1
    @Debian_yadav: The -L flag will dereference the symlink and see that it points to a file, and won't place it with the directories at the top. – Peschke Nov 30 '18 at 16:03
  • That's pretty close to great. Do you know if there's a way to get it to keep the symlink -> target notation as well? – JoshuaD Nov 30 '18 at 20:48
  • Related question: unix.stackexchange.com/questions/232394/… – JoshuaD Nov 30 '18 at 20:49
  • 2
    @JoshuaD: See my latest edit. – Peschke Nov 30 '18 at 21:33

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.