List Files in Directory with their Git Create Date

Extending ls to display the date each output file was created in a git repository.

The Command:

ls | xargs -t -I % git log --diff-filter=A -- % 2>&1 | grep "Date\|log"

Sample Output:

Produces a result like

git log --diff-filter=A -- 2018-10-31-sensor-hardware.md
Date:   Wed Oct 31 16:18:12 2018 -0400
git log --diff-filter=A -- 2018-11-05-Railroad-logos.md
Date:   Thu Nov 8 05:51:50 2018 +0000
git log --diff-filter=A -- 2018-11-09-ADSB-Guide.md
Date:   Thu Jan 24 15:00:06 2019 -0500

Breaking it down:

ls

List the files in the current directory

xargs

xargs reads items from the standard input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines, and executes the command (default is /bin/echo) one or more times with any initial-arguments followed by items read from standard input. Blank lines on the standard input are ignored.

https://linux.die.net/man/1/xargs

xargs -t -I % git log --diff-filter=A -- % 2>&1
       |                |                   |-> Combine stderr and stdout
       |                |                       Needed because -t prints to stderr
       |                |            
       |                |-> Filter commits based on what happened to the file,
       |                    "A" means only display commits where the file
       |                    was added
       |                        
       |-> Print the command that will be executed to stderr before executing it
           (This is where grep extracts the filename)

diff-filter documentation. Other useful options include C for copied and R for renamed, these options can also be combined!

If we exclude 2>&1 and grep for a moment and just run ls | xargs -t -I % git log --diff-filter=A -- % this is what we see:

git log --diff-filter=A -- 2018-10-31-sensor-hardware.md
commit 1e273670ee661839e813c859007fda2cacb670d9
Author: djbeadle <████████@█████.com>
Date:   Wed Oct 31 16:18:12 2018 -0400

    Temp Sensor Part III
git log --diff-filter=A -- 2018-11-05-Railroad-logos.md
commit e25fb5135645a2f241a1bbea003f71c09126dc8a
Author: djbeadle <████████@█████.com>
Date:   Thu Nov 8 05:51:50 2018 +0000

    Made it a markdown file
git log --diff-filter=A -- 2018-11-09-ADSB-Guide.md
commit 5ece46b85b8b7fed20ccc3b67ced29d7e5aeb0f8
Author: djbeadle <████████@█████.com>
Date:   Thu Jan 24 15:00:06 2019 -0500

    Rename ADSB post, create new post on FlaskWTF and QuillJS

(Email censored by hand to make things a little harder on the bots)

This output is useful, but it’s a little more wordy than what we would like. Also it’s split in to stderr and stdout as follows:

STDERR: git log --diff-filter=A -- 2018-10-31-sensor-hardware.md
STDOUT: commit 1e273670ee661839e813c859007fda2cacb670d9
        Author: djbeadle <████████@█████.com>
        Date:   Wed Oct 31 16:18:12 2018 -0400

            Temp Sensor Part III

We can merge that with 2>&1| and send it to the next step

grep

Nothing fancy going on here, grep "Date\|log" searches for “Date” or “log” and exports lines that contain either of them.

This finally leaves us with the following:

git log --diff-filter=A -- 2018-10-31-sensor-hardware.md
Date:   Wed Oct 31 16:18:12 2018 -0400

Further Processing

We could do something fancy to parse our output in to CSV format, but since I only need to do this for one or two files right now I just copy and paste the output in to Notepad++ and use the super userful macro feature to wrangle the text in to the exact format I need. If you haven’t used Notepad++'s macro feature you’re missing out, find it under the Macro menu!

Implementing this in bash is left as an exercise to the reader. 😉