I'm trying to come up with a script that will add license headers to certain files (depending on extension). My Bash is very average, so any guidance would be much appreciated.

I'm not quite sure what to ask for except for whether I'm making any gross mistakes.

#!/usr/bin/env bash

set -euo pipefail

shopt -s globstar nullglob extglob

lineone="Copyright (c) 2015 Acme Corp, LLC."
linetwo="Unauthorized copying of this file via any medium is strictly prohibited."
linethree="Written by John Doe <j@acme.com>, July 2015" # etc.

printf "// %s
// %s
// %s\n\n" "$lineone" "$linetwo" "$linethree" > "/tmp/$USER-license-go"

printf "{{/*
%s
%s
%s
*/}}\n\n" "$lineone" "$linetwo" "$linethree" > "/tmp/$USER-license-gohtml"

printf "# %s
# %s
# %s\n\n" "$lineone" "$linetwo" "$linethree" > "/tmp/$USER-license-shell"

typ=""
for f in **/*; do
if [[ -f $f ]]; then if ! grep -q Copyright "$f"; then
case "$f" in *.go ) typ="go" ;; *.gohtml ) typ="gohtml" ;; @(*.bash|*.conf) ) typ="shell" ;; * ) continue ;; esac cat "/tmp/$USER-license-"$typ "$f" | sponge "$f" fi fi done  • I'll have more to say tomorrow when I'm less tired and less likely to do something stupid with sed, but for now: it kind of bothers me that you don't clean up those tmpfiles. I'd set a trap for them: trap 'rm "/tmp/$USER-license-go" "/tmp/$USER-license-gohtml" "/tmp/$USER-license-shell"' EXIT right after the creation of the third tmpfile Aug 12 '15 at 4:08
• @NightShadeQueen Please post your suggestion as an answer, even if it is as brief as "You should use trap to ensure that your temp files get cleaned up." Oct 11 '15 at 19:04

This is quite fine. I have a few tips though.

The base path "/tmp/$USER-license-" appears many times. This is error prone, and it makes it difficult to change later. It would be better to put this in a variable and reuse it everywhere. ### here-document instead of printf Instead of the printf statements to generate the headers, here-documents would be simpler and better, for example: cat <EOF >"$BASEPATH"-go
// $lineone //$linetwo
// $linethree EOF  ### Tabulation Aligning things vertically like this may look nice at first: case "$f" in
*.go             ) typ="go"      ;;
*.gohtml         ) typ="gohtml"  ;;
@(*.bash|*.conf) ) typ="shell"   ;;
*                ) continue      ;;
esac


The problem with this is if you want to change something later. For example, I don't really see the purpose of the @(...) there, so I would like to simplify:

case "$f" in *.go ) typ="go" ;; *.gohtml ) typ="gohtml" ;; *.bash|*.conf ) typ="shell" ;; * ) continue ;; esac  But that broke the formatting. What do I do now? Add padding to line up the ) that is now out of line? Or update the other lines? The second option is not great, because I have to change many lines just because I changed one. Just thinking about this is actually a waste of time. Considering possible future changes, I suggest to avoid this kind of writing style, and stick to good old simple: case "$f" in
*.go) typ="go" ;;
*.gohtml) typ="gohtml" ;;
*.bash|*.conf) typ="shell" ;;
*) continue ;;
esac


### Alternative to sponge

I didn't know about sponge and moreutils, I'm really glad your has question lead me to discover these gems.

On the other hand, unfortunately sponge is not a standard command, and may not be readily available. Here's an alternative using GNU sed:

license="$BASEPATH"-$typ
sed -i -e "1r$license" -e '1{h;d}' -e '2{x;G}' "$f"

• sed -i may be readily available, but it is not standard either. Oct 11 '15 at 19:01

I may be missing something about this question because my solution seems almost too simple, so I apologize if that is the case ahead of time.

Well, if you have the license in one file (which you should) and then you have the file that you want to copy the license into, couldn't you just adopt a cat?

cat <license> <file> > <file>


Then, all you need to do is loop through each file and run this command.

• I need to insert it at the beginning of each file and each file already contains code :) Aug 12 '15 at 0:59
• @eric_lagergren I understand that. Aug 12 '15 at 1:02
• Ok. Unless I misread it your first example would've resulted me in overwriting my file. But yeah cat should work the same as sponge. Aug 12 '15 at 1:10
• Yes, I noticed that it would overwrite. I have fixed it now. Aug 12 '15 at 1:23
• Still not safe; if you're going to do to that, get a sponge from moreutils or use a tempfile. Aug 12 '15 at 3:42