How to make locate output look like `ll` or `ls -la` but nicer?
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
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