diff --git a/scripts/zfs-tests.sh b/scripts/zfs-tests.sh
index 6e9589e593..35d8eb0014 100755
--- a/scripts/zfs-tests.sh
+++ b/scripts/zfs-tests.sh
@@ -29,9 +29,9 @@
 BASE_DIR=$(dirname "$0")
 SCRIPT_COMMON=common.sh
 if [ -f "${BASE_DIR}/${SCRIPT_COMMON}" ]; then
-. "${BASE_DIR}/${SCRIPT_COMMON}"
+	. "${BASE_DIR}/${SCRIPT_COMMON}"
 else
-echo "Missing helper script ${SCRIPT_COMMON}" && exit 1
+	echo "Missing helper script ${SCRIPT_COMMON}" && exit 1
 fi
 
 PROG=zfs-tests.sh
@@ -100,7 +100,7 @@ cleanup_linux_loopback() {
 	for TEST_LOOPBACK in ${LOOPBACKS}; do
 		LOOP_DEV="${TEST_LOOPBACK##*/}"
 		DM_DEV=$(sudo "${DMSETUP}" ls 2>/dev/null | \
-		    grep "${LOOP_DEV}" | cut -f1)
+		    awk -v l="${LOOP_DEV}" '$0 ~ l {print $1}')
 
 		if [ -n "$DM_DEV" ]; then
 			sudo "${DMSETUP}" remove "${DM_DEV}" ||
@@ -133,9 +133,8 @@ cleanup() {
 		fi
 	fi
 
-	for TEST_FILE in ${FILES}; do
-		rm -f "${TEST_FILE}" >/dev/null 2>&1
-	done
+	# shellcheck disable=SC2086
+	rm -f ${FILES} >/dev/null 2>&1
 
 	if [ "$STF_PATH_REMOVE" = "yes" ] && [ -d "$STF_PATH" ]; then
 		rm -Rf "$STF_PATH"
@@ -150,28 +149,30 @@ trap cleanup EXIT
 # be dangerous and should only be used in a dedicated test environment.
 #
 cleanup_all() {
-	TEST_POOLS=$(sudo env ASAN_OPTIONS=detect_leaks=false "$ZPOOL" list -H -o name | grep testpool)
+	TEST_POOLS=$(ASAN_OPTIONS=detect_leaks=false "$ZPOOL" list -Ho name | grep testpool)
 	if [ "$UNAME" = "FreeBSD" ] ; then
 		TEST_LOOPBACKS=$(sudo "${LOSETUP}" -l)
 	else
-		TEST_LOOPBACKS=$(sudo "${LOSETUP}" -a|grep file-vdev|cut -f1 -d:)
+		TEST_LOOPBACKS=$("${LOSETUP}" -a | awk -F: '/file-vdev/ {print $1}')
 	fi
-	TEST_FILES=$(ls /var/tmp/file-vdev* 2>/dev/null)
+	TEST_FILES=$(ls "${FILEDIR}"/file-vdev* /var/tmp/file-vdev* 2>/dev/null)
 
 	msg
 	msg "--- Cleanup ---"
-	msg "Removing pool(s):     $(echo "${TEST_POOLS}" | tr '\n' ' ')"
+	# shellcheck disable=2116,2086
+	msg "Removing pool(s):     $(echo ${TEST_POOLS})"
 	for TEST_POOL in $TEST_POOLS; do
 		sudo env ASAN_OPTIONS=detect_leaks=false "$ZPOOL" destroy "${TEST_POOL}"
 	done
 
 	if [ "$UNAME" != "FreeBSD" ] ; then
-		msg "Removing dm(s):       $(sudo "${DMSETUP}" ls |
+		msg "Removing all dm(s):   $(sudo "${DMSETUP}" ls |
 		    grep loop | tr '\n' ' ')"
 		sudo "${DMSETUP}" remove_all
 	fi
 
-	msg "Removing loopback(s): $(echo "${TEST_LOOPBACKS}" | tr '\n' ' ')"
+	# shellcheck disable=2116,2086
+	msg "Removing loopback(s): $(echo ${TEST_LOOPBACKS})"
 	for TEST_LOOPBACK in $TEST_LOOPBACKS; do
 		if [ "$UNAME" = "FreeBSD" ] ; then
 			sudo "${LOSETUP}" -d -u "${TEST_LOOPBACK}"
@@ -180,10 +181,10 @@ cleanup_all() {
 		fi
 	done
 
-	msg "Removing files(s):    $(echo "${TEST_FILES}" | tr '\n' ' ')"
-	for TEST_FILE in $TEST_FILES; do
-		sudo rm -f "${TEST_FILE}"
-	done
+	# shellcheck disable=2116,2086
+	msg "Removing files(s):    $(echo ${TEST_FILES})"
+	# shellcheck disable=2086
+	sudo rm -f ${TEST_FILES}
 }
 
 #
@@ -197,19 +198,18 @@ cleanup_all() {
 #
 find_runfile() {
 	NAME=$1
-	RESULT=""
 
 	if [ -f "$RUNFILE_DIR/$NAME" ]; then
-		RESULT="$RUNFILE_DIR/$NAME"
+		echo "$RUNFILE_DIR/$NAME"
 	elif [ -f "$RUNFILE_DIR/$NAME.run" ]; then
-		RESULT="$RUNFILE_DIR/$NAME.run"
+		echo "$RUNFILE_DIR/$NAME.run"
 	elif [ -f "$NAME" ]; then
-		RESULT="$NAME"
+		echo "$NAME"
 	elif [ -f "$NAME.run" ]; then
-		RESULT="$NAME.run"
+		echo "$NAME.run"
+	else
+		return 1
 	fi
-
-	echo "$RESULT"
 }
 
 #
@@ -340,7 +340,7 @@ OPTIONS:
 	-u USER     Run single test as USER (default: root)
 
 EXAMPLES:
-# Run the default (linux) suite of tests and output the configuration used.
+# Run the default ($(echo "${DEFAULT_RUNFILES}" | sed 's/\.run//')) suite of tests and output the configuration used.
 $0 -v
 
 # Run a smaller suite of tests designed to run more quickly.
@@ -350,7 +350,7 @@ $0 -r linux-fast
 $0 -t tests/functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh
 
 # Cleanup a previous run of the test suite prior to testing, run the
-# default (linux) suite of tests and perform no cleanup on exit.
+# default ($(echo "${DEFAULT_RUNFILES}" | sed 's/\.run//')) suite of tests and perform no cleanup on exit.
 $0 -x
 
 EOF
@@ -463,8 +463,8 @@ post_user = root
 post =
 outputdir = /var/tmp/test_results
 EOF
-	SINGLETESTDIR=$(dirname "$SINGLETEST")
-	SINGLETESTFILE=$(basename "$SINGLETEST")
+	SINGLETESTDIR="${SINGLETEST%/*}"
+	SINGLETESTFILE="${SINGLETEST##*/}"
 	SETUPSCRIPT=
 	CLEANUPSCRIPT=
 
@@ -499,8 +499,8 @@ IFS=,
 for RUNFILE in $RUNFILES; do
 	if [ -n "$RUNFILE" ]; then
 		SAVED_RUNFILE="$RUNFILE"
-		RUNFILE=$(find_runfile "$RUNFILE")
-		[ -z "$RUNFILE" ] && fail "Cannot find runfile: $SAVED_RUNFILE"
+		RUNFILE=$(find_runfile "$RUNFILE") ||
+			fail "Cannot find runfile: $SAVED_RUNFILE"
 		R="$R,$RUNFILE"
 	fi
 
@@ -520,7 +520,7 @@ if [ "$(id -u)" = "0" ]; then
 	fail "This script must not be run as root."
 fi
 
-if [ "$(sudo whoami)" != "root" ]; then
+if [ "$(sudo id -un)" != "root" ]; then
 	fail "Passwordless sudo access required."
 fi
 
@@ -557,16 +557,14 @@ fi
 
 #
 # By default preserve any existing pools
-# NOTE: Since 'zpool list' outputs a newline-delimited list convert $KEEP from
-# space-delimited to newline-delimited.
 #
 if [ -z "${KEEP}" ]; then
-	KEEP="$(sudo env ASAN_OPTIONS=detect_leaks=false "$ZPOOL" list -H -o name)"
+	KEEP="$(ASAN_OPTIONS=detect_leaks=false "$ZPOOL" list -Ho name | tr -s '[:space:]' ' ')"
 	if [ -z "${KEEP}" ]; then
 		KEEP="rpool"
 	fi
 else
-	KEEP="$(echo "$KEEP" | tr '[:blank:]' '\n')"
+	KEEP="$(echo "$KEEP" | tr -s '[:space:]' ' ')"
 fi
 
 #
@@ -578,11 +576,7 @@ fi
 #
 # See libzfs/libzfs_config.c for more information.
 #
-if [ "$UNAME" = "FreeBSD" ] ; then
-	__ZFS_POOL_EXCLUDE="$(echo "$KEEP" | tr -s '\n' ' ')"
-else
-	__ZFS_POOL_EXCLUDE="$(echo "$KEEP" | sed ':a;N;s/\n/ /g;ba')"
-fi
+__ZFS_POOL_EXCLUDE="$KEEP"
 
 . "$STF_SUITE/include/default.cfg"
 
@@ -622,8 +616,7 @@ if [ -z "${DISKS}" ]; then
 				DISKS="$DISKS $MDDEVICE"
 				LOOPBACKS="$LOOPBACKS $MDDEVICE"
 			else
-				TEST_LOOPBACK=$(sudo "${LOSETUP}" -f)
-				sudo "${LOSETUP}" "${TEST_LOOPBACK}" "${TEST_FILE}" ||
+				TEST_LOOPBACK=$(sudo "${LOSETUP}" --show -f "${TEST_FILE}") ||
 				    fail "Failed: ${TEST_FILE} -> ${TEST_LOOPBACK}"
 				BASELOOPBACK="${TEST_LOOPBACK##*/}"
 				DISKS="$DISKS $BASELOOPBACK"
@@ -649,7 +642,7 @@ fi
 #
 # Disable SELinux until the ZFS Test Suite has been updated accordingly.
 #
-if [ -x "$STF_PATH/setenforce" ]; then
+if command -v setenforce >/dev/null; then
 	sudo setenforce permissive >/dev/null 2>&1
 fi
 
@@ -657,8 +650,8 @@ fi
 # Enable internal ZFS debug log and clear it.
 #
 if [ -e /sys/module/zfs/parameters/zfs_dbgmsg_enable ]; then
-	sudo /bin/sh -c "echo 1 >/sys/module/zfs/parameters/zfs_dbgmsg_enable"
-	sudo /bin/sh -c "echo 0 >/proc/spl/kstat/zfs/dbgmsg"
+	sudo sh -c "echo 1 >/sys/module/zfs/parameters/zfs_dbgmsg_enable"
+	sudo sh -c "echo 0 >/proc/spl/kstat/zfs/dbgmsg"
 fi
 
 msg
@@ -688,7 +681,6 @@ export FILEDIR
 export KEEP
 export __ZFS_POOL_EXCLUDE
 export TESTFAIL_CALLBACKS
-export PATH=$STF_PATH
 
 mktemp_file() {
 	if [ "$UNAME" = "FreeBSD" ]; then
@@ -712,7 +704,8 @@ msg "${TEST_RUNNER}" \
     "-T \"${TAGS}\"" \
     "-i \"${STF_SUITE}\"" \
     "-I \"${ITERATIONS}\""
-{ ${TEST_RUNNER} \
+{ PATH=$STF_PATH \
+    ${TEST_RUNNER} \
     ${QUIET:+-q} \
     ${KMEMLEAK:+-m} \
     ${KMSG:+-K} \
@@ -737,9 +730,10 @@ if [ "$RESULT" -eq "2" ] && [ -n "$RERUN" ]; then
 	for test_name in $MAYBES; do
 		grep "$test_name " "$TEMP_RESULTS_FILE" >>"$TEST_LIST"
 	done
-	{ ${TEST_RUNNER} \
-            ${QUIET:+-q} \
-            ${KMEMLEAK:+-m} \
+	{ PATH=$STF_PATH \
+	    ${TEST_RUNNER} \
+	        ${QUIET:+-q} \
+	        ${KMEMLEAK:+-m} \
 	    -c "${RUNFILES}" \
 	    -T "${TAGS}" \
 	    -i "${STF_SUITE}" \