2

If I last modified a file 5 minutes ago, is it possible to make ls-l output something like "5 mins" instead of the actual date/time?

Raffa
  • 34,963
B.Tanner
  • 2,685

4 Answers4

2

This is a continuation of an earlier script used for parsing
ls -l with some enhancement:

#!/bin/bash

while read -r p c u g s e n; do [[ $p = total ]] && {
echo "$p $c" 1>&2; continue;
} x=$(($EPOCHSECONDS - e)) y=$((x / 60)) z=$((x % 60)) printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n'
"$p"
"$c"
"$u"
"$g"
"$s"
"$y minutes"
"$z seconds"
"$n" done < <(
ls -LApl --color=force
--time-style=+%s
--quoting-style=shell-escape "$@"
)
| column -t -R 2,5,6,7 -s $'\t' -o ' '

1

I use stat to get metadata info on the files. Some examples:

stat -c $'%y\t%n' * | sort -n

Output looks like this:

2020-01-27 11:52:25.681249958 +0200 CHANGELOG.md

Then to lookup a single file

stat CHANGELOG.md

and output looks like this:

  File: CHANGELOG.md
  Size: 94          Blocks: 8          IO Block: 4096   regular file
  Device: fd00h/64768d  Inode: 6029378     Links: 1
  Access: (0644/-rw-r--r--)  Uid: (  998/example)   Gid: (  998/example)
  Access: 2020-11-12 17:47:34.768793021 +0200
  Modify: 2020-01-27 11:52:25.681249958 +0200
  Change: 2020-11-12 17:47:02.282093672 +0200
  Birth: -

Otherwise you might need a small bash script to show you the difference between when the file was created and current time.

 LastUpdate="$(stat -c %Y myfile)"
 now="$(date +%s)"
 let diff="${now}-${lastUpdate}"
ognjen011
  • 1,403
0

One way:

You can make ls print modification time in seconds since epoch, like so:

ls -l --time-style="+%s"

Then pipe the ls output to awk to do the logic, like so:

ls -l --time-style="+%s" | awk -v now=$(date +%s) '{$6 = now - $6; d=int($6/60/60/24); h=int($6/60/60%24); m=int($6/60%60); s=int($6%60);$6 = "="d" Days "h" Hours "m" Mins "s" Secs ago="; print}' | column -t -s'='

Because the command line is long, here is a break-up which is basically the same but can be visually more contained:

ls -l --time-style="+%s" | \
awk -v now=$(date +%s) '{\
$6 = now - $6; \
d=int($6/60/60/24); \
h=int($6/60/60%24); \
m=int($6/60%60); \
s=int($6%60);\
$6 = "="d" Days "h" Hours "m" Mins "s" Secs ago="; print}' | column -t -s'='
  • -v now=$(date +%s) will assign the current time in seconds since epoch to now

  • $6 = now - $6 will calculate the time in seconds since file last modified.

  • d=int($6/60/60/24) will calculate the days.

  • h=int($6/60/60%24) will calculate remaining hours less than one day.

  • m=int($6/60%60) will calculate remaining minutes less than one hour.

  • s=int($6%60) will calculate remaining seconds less than one minute.

  • $6 = d" Days "h" Hours "m" Mins "s" Secs ago" will change the modification date to something like 2 Days 5 Hours 3 Mins 47 Secs ago.


Another way:

You can construct your own custom ls -l alternative in a bash script, like so:

#!/bin/bash

for f in * do p=$(stat -c "%A=%h=%U=%G=%s" "$f") m=$(date -r "$f" "+%s") n=$(date "+%s") l=$((n-m)) d=$((l/60/60/24)) h=$((l/60/60%24)) m=$((l/60%60)) s=$((l%60)) echo "$p= = =$d Days=$h Hours=$m Mins=$s=Secs= = =$f" | column -t -s'=' done

or make the output simpler and less time strict, like so:

#!/bin/bash

for f in * do p=$(stat -c "%A %h %U %G %s" "$f") m=$(date -r "$f" "+%s") n=$(date "+%s") l=$((n-m)) d=$((l/60/60/24)) h=$((l/60/60%24)) m=$((l/60%60)) s=$((l%60)) if (( $d >= 1 )) then t="$d Days" elif (( $h >= 1 )) then t="$h Hours" elif (( $m >= 1 )) then t="$m Mins" else t="$s Secs" fi echo "$p= = =$t= = =$f" | column -t -s'=' done


Notice on usage:

If you save either the above command or the above script in a file in your home directory, name the file lsl.sh and make it executable like so:

chmod +x ~/lsl.sh

you can add an alias like this:

alias lsl='bash ~/lsl.sh'

to your ~/.bashrc file so you can afterwords run the short command: `

lsl

from any directory and get the desired result.

Raffa
  • 34,963
0

Answering my own question here because this is what I actually ended up doing.

I could not get any satisfactory results using anything that parsed the output of ls -l into a word stream (bash, awk, column etc) because a) filenames with spaces in messed up, and b) ls -l's aligned columns messed up (for example, right-aligned filesizes). ls -l | column -t shows both problems at once.

I will get shot down for the inefficiency in this, but this is my eventual script that uses sed to replace parts of the output of ls -l maintaining column width:

day0=`date                     +"%b %_d"`
day1=`date --date "1 day  ago" +"%b %_d"`
day2=`date --date "2 days ago" +"%b %_d"`
day3=`date --date "3 days ago" +"%b %_d"`
day4=`date --date "4 days ago" +"%b %_d"`
day5=`date --date "5 days ago" +"%b %_d"`
day6=`date --date "6 days ago" +"%b %_d"`

min0=date +&quot;%H:%M&quot; min1=date --date &quot;1 minute ago&quot; +&quot;%H:%M&quot; min2=date --date &quot;2 minutes ago&quot; +&quot;%H:%M&quot; min3=date --date &quot;3 minutes ago&quot; +&quot;%H:%M&quot; min4=date --date &quot;4 minutes ago&quot; +&quot;%H:%M&quot; min5=date --date &quot;5 minutes ago&quot; +&quot;%H:%M&quot; min6=date --date &quot;6 minutes ago&quot; +&quot;%H:%M&quot; min7=date --date &quot;7 minutes ago&quot; +&quot;%H:%M&quot; min8=date --date &quot;8 minutes ago&quot; +&quot;%H:%M&quot; min9=date --date &quot;9 minutes ago&quot; +&quot;%H:%M&quot;

ls -lh --color=force --quoting-style=shell-escape "$@"|sed "
/$day6 (.[0-9]:[0-9][0-9])/ s/$day6/6 days/; t /$day5 (.[0-9]:[0-9][0-9])/ s/$day5/5 days/; t /$day4 (.[0-9]:[0-9][0-9])/ s/$day4/4 days/; t /$day3 (.[0-9]:[0-9][0-9])/ s/$day3/3 days/; t /$day2 (.[0-9]:[0-9][0-9])/ s/$day2/2 days/; t /$day1 (.[0-9]:[0-9][0-9])/ s/$day1/yesday/; t /$day0 (.[0-9]:[0-9][0-9])/ s/$day0/ today/; T s/$min0/ now/; t s/$min1/1 min/; t s/$min2/2 min/; t s/$min3/3 min/; t s/$min4/4 min/; t s/$min5/5 min/; t s/$min6/6 min/; t s/$min7/7 min/; t s/$min8/8 min/; t s/$min9/9 min/; t "

Sample output of /var/log/syslog*:

-rw-r----- 1 syslog adm    9240  today   now /var/log/syslog
-rw-r----- 1 syslog adm 1279965  today 8 min /var/log/syslog.1
-rw-r----- 1 syslog adm   51750 2 days 14:12 /var/log/syslog.2.gz
-rw-r----- 1 syslog adm   14768 3 days 10:59 /var/log/syslog.3.gz
-rw-r----- 1 syslog adm    7767 4 days 10:04 /var/log/syslog.4.gz
-rw-r----- 1 syslog adm  119295 5 days 09:49 /var/log/syslog.5.gz
-rw-r----- 1 syslog adm   33450 6 days 13:06 /var/log/syslog.6.gz
-rw-r----- 1 syslog adm   21372 Jan 25 11:12 /var/log/syslog.7.gz

(not sure why log appears here in red; it doesn't on my terminal.)

This is only used from the command line so all those date commands don't matter, in fact I don't notice any delay at all.

Update:

time output for `ls -l /var/log/syslog*':

real    0m0.002s
user    0m0.002s
sys     0m0.000s

time output for for my new script:

real    0m0.019s
user    0m0.018s
sys     0m0.003s
B.Tanner
  • 2,685