The following Bash script takes a single parameter (the PAN) and exits with 1 if the PAN does not satisfy a [LUHN check](https://en.wikipedia.org/wiki/Luhn_algorithm).

```
#!/bin/bash

pan=$1
panlen=${#pan}

for i in $(seq $((panlen - 1)) -1 0); do
  digit=${pan:$i:1}
  if [ $(((panlen-i) % 2)) -eq 0 ]; then
     #even
     ((digit*=2))
     [ ${#digit} -eq 2 ] && digit=$((${digit:0:1}+${digit:1:1}))
  fi
  ((sum+=digit))
done

[ $((sum % 10)) -eq 0 ] || exit 1

```

For example, when placed in a file called isLUHNValid.sh it can be run with a valid PAN like:

```
./isLUHNValid.sh 4388576018410707 && echo 'Valid PAN' || echo 'Invalid PAN'

```

which will echo 'Valid PAN'.

And with an invalid PAN:

```
./isLUHNValid.sh 4388576018410708 && echo 'Valid PAN' || echo 'Invalid PAN'

```

it will echo 'Invalid PAN'.

I'm interested to know:

* if I've followed best practices; and/or
* if there's an opportunity for optimisation

I've been using Bash for a couple of years - but I'm constantly learning new things from examples on the Internet (like from [here](https://codereview.stackexchange.com/questions/95211/validating-a-credit-card-number-using-luhns-algorithm/107192#107192)) and from `man bash`. Unfortunately in my position I don't have anyone to look over my shoulder and review by Bash code so I thought I'd take advantage of this community.