For the pathname of a single one of your .md files in $pathname, somewhere in or below src:
name=$(basename "$pathname" .md)
destdir=out/$( dirname "${pathname#src/}" )
mkdir -p "$destdir" && pandoc -o "$destdir/$name.html" "$pathname"
Here, basename "$pathname" .md would be the file's name without the .md filename suffix and without any directory paths (e.g. README for src/bible/README.md), ${pathname#src/} would be the the pathname of the file without the initial src/ directory name and $destdir would be set to the destination directory pathname (src/ exchanged for out/, no final filename component, e.g. out/bible for src/bible/README.md). At the end, we let pandoc write to $destdir/$name.html (if the creation of the destination directory succeeded).
You can run this for all .md files in a directory structure:
find src -type f -name '*.md' -exec sh -c '
for pathname do
name=$(basename "$pathname" .md)
destdir=out/$( dirname "${pathname#src/}" )
mkdir -p "$destdir" && pandoc -o "$destdir/$name.html" "$pathname"
done' {} +
This is the same set of commands in a loop. We let find feed the loop with pathnames found under src (see also Understanding the -exec option of `find`).
Testing:
$ tree -F
.
`-- src/
|-- bible/
| |-- README.md
| `-- index.md
|-- index.md
`-- other.md
2 directories, 4 files
(command is being run here)
$ tree -F
.
|-- out/
| |-- bible/
| | `-- README.html
| |-- index.html
| `-- other.html
`-- src/
|-- bible/
| |-- README.md
| `-- index.md
|-- index.md
`-- other.md
4 directories, 7 files
If you want to use your SRC_DIR and OUT_DIR Makefile variables:
find $(SRC_DIR) -type f -name '*.md' -exec sh -c '
srcdir=${1%/}; outdir=$2; shift 2
for pathname do
name=$(basename "$pathname" .md)
destdir=$outdir/$( dirname "${pathname#$srcdir/}" )
mkdir -p "$destdir" && pandoc -o "$destdir/$name.html" "$pathname"
done' $(SRC_DIR) $(OUT_DIR) {} +
That is, pass the src and out names on the sh -c script's command line and pick them out inside the in-line script.
I'm not 100% sure about how the quoting in a Makefile works, and you may want to escape the newlines in the code above, alternatively create a separate little script for doing this, and then call that from the Makefile.