#!/usr/bin/env bash # vim:ts=4:sts=4:sw=4:et # # Author: Hari Sekhon # Date: 2019-08-02 13:30:09 +0100 (Fri, 02 Aug 2019) # # https://github.com/harisekhon/bash-tools # # License: see accompanying Hari Sekhon LICENSE file # # If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help steer this or other code I publish # # https://www.linkedin.com/in/harisekhon # # Checks for duplicate function or alias definitions within a given collection of bash scripts - useful for checking across many .bash.d/ includes # # This isn't caught by shellcheck - for example it's common to alias 'p' to ping, but I also do this for 'kubectl get pods' set -euo pipefail [ -n "${DEBUG:-}" ] && set -x srcdir="$(dirname "$0")" # shellcheck source=lib/utils.sh . "$srcdir/lib/utils.sh" section "Checking for Bash duplicate definitions (functions, aliases)" start_time="$(start_timer)" check_duplicate_defs(){ echo "Checking for duplicate definitions in the following files:" echo for x in "$@"; do echo "$x" done echo check_duplicate_functions "$@" check_duplicate_aliases "$@" check_duplicate_aliases_vs_functions "$@" } get_functions(){ # ignore definitions that happen inside indented blocks such as if/else statements creating conditional functions #grep -Eh '^[[:space:]]*(function[[:space:]]+)?[[:alnum:]-]+[[:space:]]*\(' "$@" 2>/dev/null | grep -Eh '^(function[[:space:]]+)?[[:alnum:]-]+[[:space:]]*\(' "$@" 2>/dev/null | grep -Ev '^[[:space:]]*for[[:space:]]*\(\(' | sed 's/^[[:space:]]*\(function[[:space:]]*\)*//; s/[[:space:]]*(.*//' | sort } get_aliases(){ grep -Eho '^[[:space:]]*alias[[:space:]]+[[:alnum:]]+=' "$@" 2>/dev/null | sed 's/^[[:space:]]*alias[[:space:]]*//; s/=$//' | sort } check_duplicate_functions(){ echo "* Checking for duplicate function definitions" echo local function_dups set +o pipefail function_dups="$(get_functions "$@" | uniq -d)" if [ -n "$function_dups" ]; then echo "Duplicate functions detected across input files!" echo for x in $function_dups; do grep -Eno "^[[:space:]]*(function[[:space:]]+)?${x}[[:space:]]*\\(" "$@" 2>/dev/null || : done echo exit 1 fi } check_duplicate_aliases(){ echo "* Checking for duplicate alias definitions" echo local alias_dups set +o pipefail alias_dups="$(get_aliases "$@" | uniq -d)" if [ -n "$alias_dups" ]; then echo "Duplicate aliases detected across input files!" echo for x in $alias_dups; do grep -Eno "^[[:space:]]*alias[[:space:]]+${x}=" "$@" 2>/dev/null || : done echo echo exit 1 fi } check_duplicate_aliases_vs_functions(){ echo "* Checking for duplicate alias vs function definitions" echo local defs local duplicate_defs defs="$(get_functions "$@") $(get_aliases "$@")" duplicate_defs="$(sort <<< "$defs" | uniq -d)" if [ -n "$duplicate_defs" ]; then echo "Duplicate function vs alias definitions detected across input files!" echo for x in $duplicate_defs; do grep -Eno -e "^[[:space:]]*alias[[:space:]]+${x}=" \ -e "^[[:space:]]*(function[[:space:]]+)?${x}[[:space:]]*\\(" \ "$@" 2>/dev/null || : done echo echo exit 1 fi } if [ $# -gt 0 ]; then check_duplicate_defs "$@" else # only this repo #check_duplicate_defs "$srcdir/.bashrc" "$srcdir"/.bash.d/*.sh # $HOME + this repo check_duplicate_defs ~/.bashrc ~/.bash.d/*.sh "$srcdir/.bashrc" "$srcdir"/.bash.d/*.sh fi time_taken "$start_time" section2 "No duplicate bash definitions found" echo