In addition to the above, you may wish to consider a few additional tweaks. When piping multiple samtools or bcftools commands together, it makes no sense to be bgzipping the output between the pipes, so make use of -u in samtools and -Ou in bcftools. Note that the sort step is something of a crunch point, so that's a logical step to save the output (which obviously avoids having to restart everything if you need to tweak the parameters for a later stage).
Eg for bam something like (untested!):
bwa mem ref.fa R1.fq.gz R2.fq.gz | \
samtools fixmate -u -m - - | \
samtools sort -@8 -u - - | \
samtools markdup -@8 - dat.bam
The fixmate -m and markdup either side of sort avoids needing an additional sorting or collation stage in duplicate marking. It gathers data about multiple alignments from the same template in the first stage, adds them to aux tags, does the sorting, and then uses those aux tags written earlier for the duplicate marking algorithm. This is therefore substantially quicker than most implementations and avoids needless temporary files and re-sorting stages. Note due to the crunch point of sort, it's unlikely the 8 threads I specified for markdup writing out of BAM will run concurrently with the 8 threads given to sort.
Then in bcftools land, something like (also untested):
bcftools mpileup -Ou -f $HREF38 dat.bam | \
bcftools call -Ou -vm - | \
bcftools norm -f $HREF38 -Oz -o dat.vcf.gz -
I may have got some options wrong there, like what needs "-" for stdin / stdout, but that's the basic gist of it. You can tweak it further, eg adding more threads to things that will benefit (sort mainly and the final BAM output) or more memory to sort, but remember it's bizarre and is the memory per-thread.
Edit: also in older versions of samtools not all commands had a -u option for uncompressed output. If you hit that problem, you can do the laborious -O bam,level=0 alternative.