2

The locate command output is a little bland:

$ time locate etc/profile
/etc/profile
/etc/profile.d
/etc/profile.d/appmenu-qt5.sh
/etc/profile.d/apps-bin-path.sh
/etc/profile.d/bash_completion.sh
/etc/profile.d/cedilla-portuguese.sh
/etc/profile.d/jdk.csh
/etc/profile.d/jdk.sh
/etc/profile.d/vte-2.91.sh

real    0m0.696s
user    0m0.671s
sys     0m0.024s

How can I give more information to it like ll or ls -la does? Perhaps include headings too?

2 Answers 2

3

Using xargs and ls:

$ locate -0 etc/profile | xargs -0 ls -ld
-rw-r--r-- 1 root root  575 Oct 23  2015 /etc/profile
drwxr-xr-x 2 root root 4096 Apr 20 10:10 /etc/profile.d
-rw-r--r-- 1 root root   40 Nov 30  2015 /etc/profile.d/appmenu-qt5.sh
-rw-r--r-- 1 root root  663 May 18  2016 /etc/profile.d/bash_completion.sh
-rw-r--r-- 1 root root 1003 Dec 29  2015 /etc/profile.d/cedilla-portuguese.sh
-rwxr-xr-x 1 root root   31 Oct 18  2017 /etc/profile.d/go.sh
-rwxr-xr-x 1 root root  301 Feb 20  2013 /etc/profile.d/jdk.csh
-rwxr-xr-x 1 root root  299 Feb 20  2013 /etc/profile.d/jdk.sh
-rw-r--r-- 1 root root  999 Aug 23  2017 /etc/profile.d/libvirt-uri.sh
-rw-r--r-- 1 root root 1941 Mar 16  2016 /etc/profile.d/vte-2.91.sh
-rw-r--r-- 1 root root 1557 Apr 15  2016 /etc/profile.d/Z97-byobu.sh
1
  • That was my initial thinking but I had my old problems with xargs and tried to use {} placeholder. Plus I wanted to take out the link count and add heading with last sudo updatedb time. Still I have a hunch most of the world will like your one-liner better. Good job! May 23, 2018 at 3:27
2

I created a script called llocate for this purpose:

$ time llocate etc/profile
ACCESS      OWNER  GROUP  SIZE  MODIFIED      NAME (updatdb last ran: 2018-07-01 11:30:05)
-rw-r--r--  root   root   575   Nov 12  2017  /etc/profile
drwxr-xr-x  root   root   4096  Jun  4 17:19  /etc/profile.d
-rw-r--r--  root   root   40    Feb 16  2017  /etc/profile.d/appmenu-qt5.sh
-rw-r--r--  root   root   580   Oct 18  2017  /etc/profile.d/apps-bin-path.sh
-rw-r--r--  root   root   663   May 18  2016  /etc/profile.d/bash_completion.sh
-rw-r--r--  root   root   1003  Dec 29  2015  /etc/profile.d/cedilla-portuguese.sh
-rwxr-xr-x  root   root   301   Feb 20  2013  /etc/profile.d/jdk.csh
-rwxr-xr-x  root   root   299   Feb 20  2013  /etc/profile.d/jdk.sh
-rw-r--r--  root   root   1941  Mar 16  2016  /etc/profile.d/vte-2.91.sh

real    0m0.760s
user    0m0.754s
sys     0m0.020s

It takes .76 seconds to run versus .70 seconds for the regular locate command. The difference is negligible.


Bash script

The bash code is fairly straight forward. Copy the script below into the directory /home/YOUR_NAME/bin (you may have to create it first) or /usr/local/bin and mark it executable using:

chmod a+x /home/YOUR_NAME/bin/llocate

Here's the script llocate:

#!/bin/bash

# NAME: llocate
# PATH: /mnt/e/bin
# DATE: May 22, 2018. Modified July 5, 2020.
# DESC: Use locate command but format output like `ll` with headings
# PARM: Parameter 1 = locate search string

# UPDT: 2018-07-01 Format date with Time or Previous Year like `ls -al`.
#       2018-11-09 Filenames trunctated after first space.
#       2020-07-05 Speed up processing. Handle permission denied.

if [[ $# -eq 0 ]]; then
    echo "First parameter must be full or partial file names to search for."
    exit 1
fi

tmpLine=$(locate "$1")

# Was anything found?
if [[ ${#tmpLine} -eq 0 ]] ; then
    echo "No files found. If files created today, did you run 'sudo updatedb' after?"
    exit 1
fi

LastRun=$(stat --printf=%y /var/lib/mlocate/mlocate.db | sed 's/\.[^\n]*//')

# Build output with columns separated by "|" for column command
tmpForm="ACCESS|OWNER|GROUP|SIZE|MODIFIED|NAME (updatdb last ran: $LastRun)"$'\n'

ThisYear=$(date +%Y)

while read -r Line; do

    StatLine=$(stat --printf='%A|%U|%G|%s|%Y|%N\n' "$Line" | sed "s/'//g")

    IFS="|" Arr=($StatLine)
    Seconds="${Arr[4]}"
    [[ $Seconds == "" ]] && continue    # Permission denied

    # Format date with time if it's this year, else use file's year
    if [[ $(date -d @$Seconds +'%Y') == "$ThisYear" ]]; then
        HumanDate=$(date -d @$Seconds +'%b %_d %H:%M')
    else
        HumanDate=$(date -d @$Seconds +'%b %_d  %Y')
    fi

    StatLine="${StatLine/$Seconds/$HumanDate}"
    tmpForm="$tmpForm$StatLine"$'\n'

done <<< "$tmpLine"    # Read next locate line.

column -t -s '|' <<< "$tmpForm"

exit 0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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