Repository: openemr/openemr-devops
Pull request #415: mws/shellcheck openemr cmd
Author: login: msummers42
Created: 2025-04-24T16:16:09Z | Merged: 2025-04-30T09:31:00Z

#### Short description of what this resolves:
This PR addresses all issues in `openemr-cmd` detected by [Shellcheck, a shell script static analyzer](https://github.com/koalaman/shellcheck) and begins to align the script's conventions and style with [Google's shell guide](https://google.github.io/styleguide/shellguide.html). This should aid in maintainability as well as preventing defects.

It's easy and useful to debug this script using `bash -x ./openemr-cmd` in the `utilities/openemr-cmd` directory.

#### Changes proposed in this pull request:
Beyond a purely cosmetic fixes for some typos & indentation, this PR adds "strict mode", consistent variable quoting, standardizes the use of the bracket test construct. I've added a couple of functions to help clean up & centralize the in-container invocation of the devtools script. I saw an issue discussing moving that somewhere else. If that change occurs, it will be easy to support forwards/backwards compatibility by adding a little logic around the declaration of the  `DEV_TOOLS` variable.

There is a lot of opportunity to further refactor,  so I'm thinking of this as a first pass.

Also added function to treat the issue of backwards/forwards compatibility with docker compose v2, issue here https://github.com/openemr/openemr-devops/issues/396


Diff:
diff --git a/utilities/openemr-cmd/openemr-cmd b/utilities/openemr-cmd/openemr-cmd
index 5444658c..5e7b78ae 100755
--- a/utilities/openemr-cmd/openemr-cmd
+++ b/utilities/openemr-cmd/openemr-cmd
@@ -1,16 +1,22 @@
 #!/bin/bash
+
+# Exit on error, unset var, pipe failure
+set -euo pipefail
+
 ################################################################################################
 # Function  : Manage the docker command line
 # Version   : See below --version section
 # Copyright : Copyright (c) 2020 Reid Liu <guliu@redhat.com>
 # Copyright : Copyright (c) 2020-2025 Brady Miller <brady.g.miller@gmail.com>
+# Copyright : Copyright (c) 2025 Matt Summers <matt@openCoreEMR.com> 
 # Author    : Reid Liu <guliu@redhat.com>
 # Author    : Brady Miller <brady.g.miller@gmail.com>
+# Author    : Matt Summers <matt@openCoreEMR.com>
 # License   : https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
 #################################################################################################
 
 # Increment the version when modify script
-VERSION="1.0.19"
+VERSION="1.0.20"
 
 # If the docker is snap or non-snap docker
 # Setting the container names accordingly
@@ -24,267 +30,314 @@ get_container_names() {
 # Set the container names
 get_container_names
 
+# Function to run the devtools script inside the specified container
+# Usage: run_devtools_in_docker <container_id> <devtools_command> [args...]
+run_devtools_in_docker() {
+  local container_id="$1"
+  shift # Remove container_id from arguments
+  # DEV_TOOLS is '/root/devtools'
+  # "$@" passes the remaining arguments (devtools command and its args) correctly quoted
+  docker exec -i "${container_id}" "${DEV_TOOLS}" "$@"
+}
+
+# Function to run an arbitrary shell command string inside the specified container
+# Usage: run_shell_command_in_docker <container_id> <command_string>
+run_shell_command_in_docker() {
+  local container_id="$1"
+  local command_string="$2"
+  docker exec -i "${container_id}" sh -c "${command_string}"
+}
+
 # Set some constants
-DOCKER_EXEC_CMD='docker exec -i'                                 # docker exec command
-SHELL_TYPE='sh -c'                                               # specify shell type
-FIRST_ARG=$1											                               # define the first parameter
-DEV_TOOLS=/root/devtools
-
-check_docker_compose_install_or_not(){
-	DOCKER_COMPOSE_CODE=22
-	which docker-compose &>/dev/null
-	[ $? -ne 0 ] && echo "Please check docker-compose install or not." && exit $DOCKER_COMPOSE_CODE
+FIRST_ARG="${1:-}" # define the first parameter, default to empty if not set
+DEV_TOOLS='/root/devtools'
+
+check_docker_compose_install(){
+	local DOCKER_COMPOSE_CODE=22
+    # Using an array due to variable expansion for the resulting command
+    # Check for 'docker compose' (plugin syntax) first
+    if docker compose &>/dev/null; then
+        DOCKER_COMPOSE_CMD=(docker compose)
+    # If plugin not found, check for 'docker-compose' (standalone)
+    elif command -v docker-compose &>/dev/null; then
+        DOCKER_COMPOSE_CMD=(docker-compose)
+    else
+        # Neither found, error out.
+        echo "Error: Neither 'docker compose' (plugin) nor 'docker-compose' (standalone) found." >&2
+        echo "Please ensure Docker Compose is installed correctly." >&2
+        exit "${DOCKER_COMPOSE_CODE}"
+    fi
+}
+
+# Function to run the determined docker compose command
+# Usage: run_docker_compose <compose_args...>
+run_docker_compose() {
+    check_docker_compose_install
+    # Ensure the command has been determined
+    if [[ "${#DOCKER_COMPOSE_CMD[@]}" -eq 0 ]]; then
+        echo "Error: Docker Compose command not determined." >&2
+        exit 1
+    fi
+    # Execute the stored command with provided arguments
+    "${DOCKER_COMPOSE_CMD[@]}" "$@"
 }
 
 quick_open_a_docker_shell(){
-  docker exec -w /var/www/localhost/htdocs/openemr -it $CONTAINER_ID sh
+  docker exec -w /var/www/localhost/htdocs/openemr -it "${CONTAINER_ID}" sh
 }
 
 quick_open_a_maria_docker_shell(){
-  docker exec -it $MARIADB_CONTAINER_ID /bin/bash
+  docker exec -it "${MARIADB_CONTAINER_ID}" /bin/bash
 }
 
 execute_command_flexible(){
-	if [ $# -lt 1 ]
-	then
+	if [[ $# -lt 1 ]]; then
 		echo "Please provide the command."
-		echo "e.g. `basename $0` [exec|e] \"tail -f /var/log/apache2/error.log\""
-		echo "e.g. `basename $0` -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. ${0##*/} [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. ${0##*/} -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$@"
+		# Use the function for arbitrary commands
+		run_shell_command_in_docker "${CONTAINER_ID}" "$@"
 	fi
 }
 
 check_docker_log() {
-  docker logs $CONTAINER_ID
+  docker logs "${CONTAINER_ID}"
 }
 
 check_docker_names() {
-	CHECK_NAME=$1     # specify the checking name
-	if [ $# -eq 1 ]
-	then
+	if [[ $# -eq 1 ]]; then
 		# ARGS: couchdb php fhir mariadb mysql nginx openemr openldap orthanc redis.
+        # specify the name to check
+        local CHECK_NAME="$1"
 		echo '===Check the single Docker Name==='
 		echo '  STATUS        NAME'
-		docker ps -a --format "{{.Status}}\t{{.Names}}"| grep $CHECK_NAME
+        # Capture output, check if empty
+        local matching_container
+        matching_container=$(docker ps -a --format "{{.Status}}\t{{.Names}}"| grep "${CHECK_NAME}" || true) # Keep || true here, and below, to prevent exit during capture
+        if [[ -z "${matching_container}" ]]; then
+            echo "No containers found matching '${CHECK_NAME}'"
+        else
+            echo "${matching_container}"
+        fi
 
 	else
 		# Show all the docker names.
 		echo '***************************************************************'
 		echo 'Show all the docker names by default.'
 		echo 'Please provide the keyword if you want to check the single one.'
-		echo "e.g `basename $0` [docker-names|dn] php"
+		echo "e.g $(basename "$0") [docker-names|dn] php"
 		echo '***************************************************************'
 		echo '=======Running Docker Names======='
-		docker ps | awk '{print $NF}'|grep -v NAMES|sort -n
+		
+        # Capture output, check if empty
+        local running_containers
+        running_containers=$(docker ps --format "{{.Status}}\t{{.Names}}" | { grep -v NAMES || true; } | sort -n)
+        if [[ -z "${running_containers}" ]]; then
+            echo "No running containers found."
+        else
+		    echo '  STATUS        NAME'
+            echo "${running_containers}"
+        fi
 		echo '====Other Docker Status Names====='
-		docker ps -a --format "table{{.Status}}\t{{.Names}}"| grep -v Up
+        # Capture output, check if empty
+        local other_containers
+        other_containers=$(docker ps -a --format "{{.Status}}\t{{.Names}}" | grep -v Up || true)
+        if [[ -z "${other_containers}" ]]; then
+            echo "No containers found with other statuses."
+        else
+		    echo '  STATUS        NAME'
+            echo "${other_containers}"
+        fi
 	fi
 }
 
 restart_couchdb_docker(){
-  if [ -z "$COUCHDB_CONTAINER" ]
-  then
+  if [[ -z "${COUCHDB_CONTAINER}" ]]; then
     echo "Unable to find the couchdb docker, so could not restart it"
   else
     echo "Restarting couchdb docker"
-    docker restart "$COUCHDB_CONTAINER"
+    docker restart "${COUCHDB_CONTAINER}"
   fi
 }
 
 creat_a_backup_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=20
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=20
+    if [[ $# != 1 ]]; then
 		echo 'Please provide a snapshot name.'
 		echo 'e.g. openemr-cmd [backup-snapshot|bs] example'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS backup $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" backup "${BACKUP_FILE}"
 	fi
 }
 
 restore_from_a_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=21
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=21
+    if [[ $# != 1 ]]; then
         echo 'Please provide a restore snapshot name.'
         echo 'e.g. openemr-cmd [restore-snapshot|rs] example'
-        exit $BACKUP_FILE_CODE
+        exit "${BACKUP_FILE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS restore $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" restore "${BACKUP_FILE}"
 	fi
 }
 
 copy_capsule_from_docker_to_host(){
-	BACKUP_FILE=$1
-	BACKUP_HOST_DIR=$2 #optional parameter
-	BACKUP_FILE_CODE=19
-	if [ $# != 1 ] && [ $# != 2 ]
-	then
+	local BACKUP_FILE="$1"
+	local BACKUP_HOST_DIR="${2:-}" #optional parameter, default to empty
+	local BACKUP_FILE_CODE=19
+	if (( $# != 1 && $# != 2 )); then
 		echo 'Please provide the capsule name.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz'
 		echo 'An optional setting is the path to save to. If nothing provided, then will save in current directory.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz /path/to/save'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-	  if [ -z "$BACKUP_HOST_DIR" ]
-	  then
-		  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE .
+	  if [[ -z "${BACKUP_HOST_DIR}" ]]; then
+		  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" .
     else
-      	  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE "${BACKUP_HOST_DIR}/"
+      	  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" "${BACKUP_HOST_DIR}/"
     fi
 	fi
 }
 
 copy_capsule_from_host_to_docker(){
 	# Need a capsule parameter
-	BACKUP_FILE=$1
-	CP_CAP_DIR_DKR_CODE=15
-	BACKUP_FILE_CODE=18
-	if [ $# != 1 ]
-	then
+	local BACKUP_FILE="$1"
+	local CP_CAP_DIR_DKR_CODE=15
+	local BACKUP_FILE_CODE=18
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the capsule file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [put-capsule|pc] example.tgz'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		ls $BACKUP_FILE  &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${BACKUP_FILE}" &>/dev/null; then
 			echo 'Please check whether the capsule file exists or not'
-			exit $CP_CAP_DIR_DKR_CODE
+			exit "${CP_CAP_DIR_DKR_CODE}"
 		else
-			docker cp $BACKUP_FILE  ${CONTAINER_ID}:/snapshots/
+			docker cp "${BACKUP_FILE}" "${CONTAINER_ID}:/snapshots/"
 		fi
 	fi
 }
 
 ensure_current_ver_with_upgrade_ver(){
   # Need a version parameter
-  UPGRADE_FROM_VERSION=$1
-  BACKUP_FILE_CODE=22
-	if [ $# != 1 ]
-	then
+  local UPGRADE_FROM_VERSION="$1"
+  local BACKUP_FILE_CODE=22
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the OpenEMR version to upgrade database from.'
 		echo 'e.g. openemr-cmd [ensure-version|ev] 5.0.2'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS upgrade ${UPGRADE_FROM_VERSION}"
+    # Use the devtools function
+    run_devtools_in_docker "${CONTAINER_ID}" upgrade "${UPGRADE_FROM_VERSION}"
 	fi
 }
 
 change_db_character_set_and_collation(){
-	CHARACTER_SET_COLLATION_CODE=17
-	if [ $# != 2 ]
-	then
+	local CHARACTER_SET_COLLATION_CODE=17
+	if [[ $# != 2 ]]; then
 		echo 'Please provide two parameters.'
 		echo 'e.g. openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_general_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_unicode_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_vietnamese_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8 utf8_general_ci'
-		exit $CHARACTER_SET_COLLATION_CODE
+		exit "${CHARACTER_SET_COLLATION_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS change-encoding-collation $1 $2"
+		# Use the devtools function, passing both arguments
+		run_devtools_in_docker "${CONTAINER_ID}" change-encoding-collation "$1" "$2"
 	fi
 }
 
 setup-client-cert(){
-    CERT_PACKAGE=$1
-    CERT_PACKAGE_CODE=30
-    if [ $# != 1 ]
-    then
+    local CERT_PACKAGE="$1"
+    local CERT_PACKAGE_CODE=30
+    if [[ $# != 1 ]]; then
         echo 'Please provide a certificate package name.'
         echo 'e.g. openemr-cmd [scc|setup-client-cert] sll'
-        exit $CERT_PACKAGE_CODE
+        exit "${CERT_PACKAGE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS setup-client-cert $CERT_PACKAGE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" setup-client-cert "${CERT_PACKAGE}"
 	fi
 }
 
 put-client-cert(){
 	# Need a capsule parameter
-	CERT_PACKAGE_FILE=$1
-	PUT_CLIENT_CERT_CODE=32
-	CERT_PACKAGE_FILE_CODE=31
-	if [ $# != 1 ]
-	then
+	local CERT_PACKAGE_FILE="$1"
+	local PUT_CLIENT_CERT_CODE=32
+	local CERT_PACKAGE_FILE_CODE=31
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the certificate package file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [pcc|put-client-cert] sll.zip'
-		exit $CERT_PACKAGE_FILE_CODE
+		exit "${CERT_PACKAGE_FILE_CODE}"
 	else
-		ls $CERT_PACKAGE_FILE &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${CERT_PACKAGE_FILE}" &>/dev/null; then
 			echo 'Please check whether the certificate package file exists or not'
-			exit $PUT_CLIENT_CERT_CODE
+			exit "${PUT_CLIENT_CERT_CODE}"
 		else
-			docker cp $CERT_PACKAGE_FILE ${CONTAINER_ID}:/certs/
+			docker cp "${CERT_PACKAGE_FILE}" "${CONTAINER_ID}:/certs/"
 		fi
 	fi
 }
 
 import-random-patients(){
-  if [ $# == 2 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1 $2"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" import-random-patients "$@"
 }
 
 register-oauth2-client-demo(){
-  $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client-demo $1"
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client-demo "$@"
 }
 
 register-oauth2-client(){
-  if [ $# == 1 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client $1"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client "$@"
 }
 
 set-swagger-to-multisite(){
-    if [ $# == 1 ]
-    then
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite $1"
-    else
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite"
-    fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" set-swagger-to-multisite "$@"
 }
 
 set-webroot(){
-    if [ $# == 1 ]
-    then
+    local sed_command
+    if (( $# == 1 )); then
       # assume the openemr parameter was given, so set openemr webroot
       echo "changing webroot to openemr"
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs@g' /etc/apache2/conf.d/openemr.conf"
+      sed_command="sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs@g' /etc/apache2/conf.d/openemr.conf"
     else
       # set to blank, so set blank webroot
       echo "changing webroot to blank"
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs/openemr@g' /etc/apache2/conf.d/openemr.conf"
+      sed_command="sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs/openemr@g' /etc/apache2/conf.d/openemr.conf"
     fi
+    # Use the function for arbitrary commands
+    run_shell_command_in_docker "${CONTAINER_ID}" "${sed_command}"
     # restart the docker
     echo "restarting openemr docker so the apache configuration change will take effect"
-    docker restart "$CONTAINER_ID"
+    docker restart "${CONTAINER_ID}"
 }
 
 docker-pull-image(){
+    local docker_images
     docker_images=$(docker ps --format "table {{.Image}}")
-    for IMAGE in $docker_images
-    do
-    if [ $IMAGE != "IMAGE" ] 
-    then
-      read -e -p "Do you wish to pull $IMAGE ? (y) " RESP
-      if [ "$RESP" = "y" ]; then 
-        docker pull "$IMAGE";
-      else 
-        echo "Skipping $IMAGE";
+    local IMAGE RESP
+    for IMAGE in ${docker_images}; do
+      if [[ "${IMAGE}" != "IMAGE" ]]; then
+        # Use -r with read
+        read -r -e -p "Do you wish to pull ${IMAGE} ? (y) " RESP
+        if [[ "${RESP,,}" = y ]]; then
+          docker pull "${IMAGE}"
+        else
+          echo "Skipping ${IMAGE}"
+        fi
       fi
-    fi  
     done
 }
 
@@ -294,15 +347,16 @@ FINAL_EXIT_CODE=0
 
 # Confirm the docker install or not.
 DOCKER_CODE=16
-which docker &>/dev/null
-[ $? -ne 0 ] && echo "Please check docker install or not." && exit $DOCKER_CODE
+if ! command -v docker &>/dev/null; then
+  echo "Please check docker install or not."
+  exit "${DOCKER_CODE}"
+fi
 
 # Script usage.
-if [ $# -eq 0 ] || [ "$FIRST_ARG" == '--help' ] || [ "$FIRST_ARG" == '-h' ]
-then
+if [[ $# -eq 0 || "${FIRST_ARG}" = '--help' || "${FIRST_ARG}" = '-h' ]]; then
   echo ""
-  echo "Usage: `basename $0` COMMAND [ARGS]"
-  echo "Usage: `basename $0` -d <docker name> COMMAND [ARGS]"
+  echo "Usage: ${0##*/} COMMAND [ARGS]"
+  echo "Usage: ${0##*/} -d <docker name> COMMAND [ARGS]"
   echo "Options:"
   echo "  -h, --help                         Show the commands usage"
   echo "  -v, --version                      Show the openemr-cmd command version"
@@ -321,140 +375,163 @@ then
   echo "  dpi, docker-pull-image             Prompt to pull docker image"
   echo 'php-management:'
   echo "  bt, build-themes                   Make changes to any files on your local file system"
-	echo "  pl, php-log                        To check PHP error logs"
-	echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
-	echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
-	echo "  ltr, lint-themes-report            To create a report of theme styling issues"
-	echo "  ltf, lint-themes-fix               To fix theme styling issues"
+  echo "  pl, php-log                        To check PHP error logs"
+  echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
+  echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
+  echo "  ltr, lint-themes-report            To create a report of theme styling issues"
+  echo "  ltf, lint-themes-fix               To fix theme styling issues"
   echo "  ljr, lint-javascript-report        To create a report of javascript styling issues"
   echo "  ljf, lint-javascript-fix           To fix javascript styling issues"
-	echo "  pp, php-parserror                  To check PHP parsing errors"
-	echo "  xl, xdebug-log                     To check xdebug log"
-	echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
+  echo "  pp, php-parserror                  To check PHP parsing errors"
+  echo "  xl, xdebug-log                     To check xdebug log"
+  echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
   echo 'test-management:'
-	echo "  ut, unit-test                      To run php unit testing"
-	echo "  jut, javascript-unit-test          To run javascript unit testing"
-	echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
-	echo "  at, api-test                       To run api testing"
-	echo "  et, e2e-test                       To run e2e testing"
-	echo "  st, services-test                  To run services testing"
-	echo "  ft, fixtures-test                  To run fixtures testing"
-	echo "  vt, validators-test                To run validators testing"
-	echo "  ct, controllers-test               To run controllers testing"
-	echo "  ctt, common-test                   To run common testing"
+  echo "  ut, unit-test                      To run php unit testing"
+  echo "  jut, javascript-unit-test          To run javascript unit testing"
+  echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
+  echo "  at, api-test                       To run api testing"
+  echo "  et, e2e-test                       To run e2e testing"
+  echo "  st, services-test                  To run services testing"
+  echo "  ft, fixtures-test                  To run fixtures testing"
+  echo "  vt, validators-test                To run validators testing"
+  echo "  ct, controllers-test               To run controllers testing"
+  echo "  ctt, common-test                   To run common testing"
   echo 'sweep-management:'
-	echo "  cs, clean-sweep                    To run the entire dev tool suite"
-	echo "  cst, clean-sweep-tests             To run only all the automated tests"
-  echo 'reset-mamagement:'
-	echo "  dr, dev-reset                      To reset OpenEMR only"
-	echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
-	echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
-	echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
+  echo "  cs, clean-sweep                    To run the entire dev tool suite"
+  echo "  cst, clean-sweep-tests             To run only all the automated tests"
+  echo 'reset-management:'
+  echo "  dr, dev-reset                      To reset OpenEMR only"
+  echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
+  echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
+  echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
   echo 'backup-management:'
-	echo "  bs, backup-snapshot                Create a backup snapshot"
-	echo "  rs, restore-snapshot               Restore from a snapshot"
-	echo "  ls, list-snapshots                 To list the snapshots"
-	echo "  lc, list-capsules                  List the capsules"
-	echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
-	echo "  pc, put-capsule                    Copy the capsule into the docker"
+  echo "  bs, backup-snapshot                Create a backup snapshot"
+  echo "  rs, restore-snapshot               Restore from a snapshot"
+  echo "  ls, list-snapshots                 To list the snapshots"
+  echo "  lc, list-capsules                  List the capsules"
+  echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
+  echo "  pc, put-capsule                    Copy the capsule into the docker"
   echo 'ssl-management:'
-	echo "  fh, force-https                    Force https"
-	echo "  ufh, un-force-https                Removing forcing of https"
-	echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
-	echo "  scc, setup-client-cert             Turn on client based cert with designated package"
-	echo "  lcc, list-client-certs             To list the certificate packages"
-	echo "  pcc, put-client-cert               To copy certificate package into the docker"
-	echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
+  echo "  fh, force-https                    Force https"
+  echo "  ufh, un-force-https                Removing forcing of https"
+  echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
+  echo "  scc, setup-client-cert             Turn on client based cert with designated package"
+  echo "  lcc, list-client-certs             To list the certificate packages"
+  echo "  pcc, put-client-cert               To copy certificate package into the docker"
+  echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
   echo "  sso, sql-ssl-off                   Remove testing sql ssl CA cert"
   echo "  ssc, sql-ssl-client                Use testing sql ssl client certs"
   echo "  ssco, sql-ssl-client-off           Remove testing sql ssl client certs"
-	echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
+  echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
   echo "  cso, couchdb-ssl-off               Remove testing couchdb ssl CA cert"
   echo "  csc, couchdb-ssl-client            Use testing couchdb ssl client certs"
   echo "  csco, couchdb-ssl-client-off       Remove testing couchdb ssl client certs"
-	echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
+  echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
   echo "  lso, ldap-ssl-off                  Remove testing ldap ssl CA cert"
   echo "  lsc, ldap-ssl-client               Use testing ldap ssl client certs"
   echo "  lsco, ldap-ssl-client-off          Remove testing ldap ssl client certs"
   echo 'multisite-management:'
   echo "  lm, list-multisites                List multisites"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
-	echo "  em, enable-multisite               Turn on support for multisite in setup.php"
-	echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  em, enable-multisite               Turn on support for multisite in setup.php"
+  echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
   echo 'api-management:'
   echo "  bad, build-api-docs                Build and place api documentation/configuration for swagger"
   echo "  roc, register-oauth2-client        Register oauth2 client (returns client id/secret)"
   echo "  rocd, register-oauth2-client-demo  Register oauth2 client (returns client id/secret) on online demo"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
   echo 'computational-health-informatics:'
-	echo "  irp, import-random-patients        Create and import random patients <number patients>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  irp, import-random-patients        Create and import random patients <number patients>"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
   echo 'webroot-management:'
-	echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
-	echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
+  echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
+  echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
   echo 'others:'
-	echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
-	echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
-	echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
-	echo "  ec, encoding-collation             Change the database character set and collation"
-
-	exit $USAGE_EXIT_CODE
-elif [ "$FIRST_ARG" == '--version' ] || [ "$FIRST_ARG" == '-v' ]
-then
-	echo "openemr-cmd $VERSION"
-	exit $VERSION_EXIT_CODE
+  echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
+  echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
+  echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
+  echo "  ec, encoding-collation             Change the database character set and collation"
+
+  exit "${USAGE_EXIT_CODE}"
+
+elif [[ "${FIRST_ARG}" = '--version' || "${FIRST_ARG}" = '-v' ]]; then
+	echo "openemr-cmd ${VERSION}"
+	exit "${VERSION_EXIT_CODE}"
 fi
 
 # Specify the docker id/name to execute the commands.
-#  default to insane dev docker, if exists
-CONTAINER_ID=$(docker ps | grep $INSANE_DEV_DOCKER | cut -f 1 -d " ")
-if [ -z $CONTAINER_ID ]
-then
-  # else, default to easy dev docker, if exists
-  CONTAINER_ID=$(docker ps | grep $EASY_DEV_DOCKER | cut -f 1 -d " ")
+# Default to insane dev docker, if exists, otherwise easy dev docker.
+# Try to find the insane dev docker ID directly
+if insane_id=$(docker ps --filter "name=${INSANE_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${insane_id}" ]]; then
+  CONTAINER_ID="${insane_id}"
+# Try to find the easy dev docker ID directly
+elif easy_id=$(docker ps --filter "name=${EASY_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${easy_id}" ]]; then
+  CONTAINER_ID="${easy_id}"
+else
+  # Neither container found running, set CONTAINER_ID to empty.
+  # The script's later logic handles the -d flag or errors if no container is specified.
+  CONTAINER_ID=""
 fi
+
 # override the default container setting if supplied via the -d parameter
 #  (also removing no longer needed parameters via shift)
 CHANGE_CONTAINER_CODE=25
-if [ "$FIRST_ARG" == '-d' ] && [ $# -ge 3 ]
-then
-	CONTAINER_ID=$2
-	FIRST_ARG=$3
-	shift 3
-elif [ "$FIRST_ARG" == '-d' ] && [ $# -lt 3 ]
-then
-	echo 'Please provide a docker id/name when using -d parameter.'
-	echo 'e.g. openemr-cmd -d docker_openemr-7-3-redis-312_1 dl'
-	exit $CHANGE_CONTAINER_CODE
+if [[ "${FIRST_ARG}" = '-d' ]]; then
+  if (( $# < 3 )); then
+    echo 'Please provide a docker id/name when using -d parameter.'
+    echo 'e.g. openemr-cmd -d docker_openemr-7-3-redis-312_1 dl'
+    exit "${CHANGE_CONTAINER_CODE}"
+  fi
+  CONTAINER_ID="$2"
+  FIRST_ARG="$3"
+  shift 3
 else
   shift
 fi
 
 #collect the couchdb docker name
-COUCHDB_CONTAINER=$(docker ps | grep $COUCHDB_DOCKER | cut -f 1 -d " ")
+# Use docker ps --filter and --format for efficiency and robustness
+couchdb_id=$(docker ps --filter "name=${COUCHDB_DOCKER}" --format "{{.ID}}" | head -n 1)
+COUCHDB_CONTAINER="${couchdb_id:-}" # Set to empty if not found
 
 # Collect the mariadb container id
-MARIADB_CONTAINER_ID=$(docker ps | grep $MARIADB_DOCKER | cut -f 1 -d " ")
+# Use docker ps --filter and --format for efficiency and robustness
+mariadb_id=$(docker ps --filter "name=${MARIADB_DOCKER}" --format "{{.ID}}" | head -n 1)
+MARIADB_CONTAINER_ID="${mariadb_id:-}" # Set to empty if not found
+
+# Check if a target container ID was determined or provided before proceeding with commands that need it
+# (Allow proceeding if the command doesn't require a container, like up, down, start, stop, --help, --version)
+case "${FIRST_ARG}" in
+  up|down|start|stop|--help|-h|--version|-v)
+    # These commands don't necessarily need a running container ID determined here
+    ;;
+  *)
+    # All other commands likely need a CONTAINER_ID
+    # Check if CONTAINER_ID is empty AND -d wasn't the *original* first arg
+    if [[ -z "${CONTAINER_ID}" && "${FIRST_ARG}" != '-d' ]]; then
+      echo "Error: Could not automatically determine target OpenEMR container (tried '${INSANE_DEV_DOCKER}' and '${EASY_DEV_DOCKER}')." >&2
+      echo "Use -d <container_name_or_id> to specify the target container." >&2
+      exit 1
+    fi
+    # If -d was used, CONTAINER_ID was set in the parameter parsing block
+    ;;
+esac
 
 # See how we were called.
 # For the shift usage, it used to cover the insane env.
-case "$FIRST_ARG" in
+case "${FIRST_ARG}" in
 	up)
-		check_docker_compose_install_or_not
-		docker-compose up -d
+		run_docker_compose up -d
 		;;
 	down)
-		check_docker_compose_install_or_not
-		docker-compose down -v
+		run_docker_compose down -v
 		;;
 	stop)
-		check_docker_compose_install_or_not
-		docker-compose stop
+		run_docker_compose stop
 		;;
 	start)
-		check_docker_compose_install_or_not
-		docker-compose start
+		run_docker_compose start
 		;;
 	s|shell)
 		quick_open_a_docker_shell
@@ -496,190 +573,191 @@ case "$FIRST_ARG" in
 	pcc|put-client-cert)
 		put-client-cert "$@"
 		;;
-  irp|import-random-patients)
-    import-random-patients "$@"
-		;;
-  rocd|register-oauth2-client-demo)
-    register-oauth2-client-demo "$@"
-		;;
-  roc|register-oauth2-client)
-    register-oauth2-client "$@"
-		;;
-  swtm|set-swagger-to-multisite)
-    set-swagger-to-multisite "$@"
-		;;
-  cwb|change-webroot-blank)
-    set-webroot
-		;;
-  cwo|change-webroot-openemr)
-    set-webroot openemr
-		;;
-  ms|maria-shell)
-    quick_open_a_maria_docker_shell
-		;;
+    irp|import-random-patients)
+        import-random-patients "$@"
+        ;;
+    rocd|register-oauth2-client-demo)
+        register-oauth2-client-demo "$@"
+        ;;
+    roc|register-oauth2-client)
+        register-oauth2-client "$@"
+        ;;
+    swtm|set-swagger-to-multisite)
+        set-swagger-to-multisite "$@"
+        ;;
+    cwb|change-webroot-blank)
+        set-webroot
+        ;;
+    cwo|change-webroot-openemr)
+        set-webroot openemr
+        ;;
+    ms|maria-shell)
+        quick_open_a_maria_docker_shell
+        ;;
 	bt)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS build-themes"
+		run_devtools_in_docker "${CONTAINER_ID}" build-themes
 		;;
 	pl)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS php-log"
+		run_devtools_in_docker "${CONTAINER_ID}" php-log
 		;;
 	pr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS psr12-report"
+		run_devtools_in_docker "${CONTAINER_ID}" psr12-report
 		;;
 	pf)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS psr12-fix"
+		run_devtools_in_docker "${CONTAINER_ID}" psr12-fix
 		;;
 	ltr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-themes-report"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-themes-report
 		;;
 	ltf)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-themes-fix"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-themes-fix
 		;;
 	ljr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-javascript-report"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-javascript-report
 		;;
 	ljf)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-javascript-fix"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-javascript-fix
 		;;
 	pp)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS php-parserror"
+		run_devtools_in_docker "${CONTAINER_ID}" php-parserror
 		;;
 	ut)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS unit-test"
+		run_devtools_in_docker "${CONTAINER_ID}" unit-test
 		;;
 	jut)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS javascript-unit-test"
+		run_devtools_in_docker "${CONTAINER_ID}" javascript-unit-test
 		;;
 	jrb)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS jut-reports-build"
+		run_devtools_in_docker "${CONTAINER_ID}" jut-reports-build
 		;;
 	at)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS api-test"
+		run_devtools_in_docker "${CONTAINER_ID}" api-test
 		;;
 	et)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS e2e-test"
+		run_devtools_in_docker "${CONTAINER_ID}" e2e-test
 		;;
 	st)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS services-test"
+		run_devtools_in_docker "${CONTAINER_ID}" services-test
 		;;
 	ft)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS fixtures-test"
+		run_devtools_in_docker "${CONTAINER_ID}" fixtures-test
 		;;
 	vt)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS validators-test"
+		run_devtools_in_docker "${CONTAINER_ID}" validators-test
 		;;
 	ct)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS controllers-test"
+		run_devtools_in_docker "${CONTAINER_ID}" controllers-test
 		;;
 	ctt)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS common-test"
+		run_devtools_in_docker "${CONTAINER_ID}" common-test
 		;;
 	cs)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS clean-sweep"
+		run_devtools_in_docker "${CONTAINER_ID}" clean-sweep
 		;;
 	cst)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS clean-sweep-tests"
+		run_devtools_in_docker "${CONTAINER_ID}" clean-sweep-tests
 		;;
 	dr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-reset"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-reset
 		restart_couchdb_docker
 		;;
 	di)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-install"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-install
 		restart_couchdb_docker
 		;;
 	dri)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-reset-install"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-reset-install
 		restart_couchdb_docker
 		;;
 	drid)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-reset-install-demodata"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-reset-install-demodata
 		restart_couchdb_docker
 		;;
 	ls)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-snapshots"
+		run_devtools_in_docker "${CONTAINER_ID}" list-snapshots
 		;;
 	lc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-capsules"
+		run_devtools_in_docker "${CONTAINER_ID}" list-capsules
 		;;
 	em)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS enable-multisite"
+		run_devtools_in_docker "${CONTAINER_ID}" enable-multisite
 		;;
 	dm)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS disable-multisite"
+		run_devtools_in_docker "${CONTAINER_ID}" disable-multisite
 		;;
 	fh)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS force-https"
+		run_devtools_in_docker "${CONTAINER_ID}" force-https
 		;;
 	ufh)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS un-force-https"
+		run_devtools_in_docker "${CONTAINER_ID}" un-force-https
 		;;
 	ossc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS on-self-signed-cert"
+		run_devtools_in_docker "${CONTAINER_ID}" on-self-signed-cert
 		;;
 	lcc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-client-certs"
+		run_devtools_in_docker "${CONTAINER_ID}" list-client-certs
 		;;
 	ss)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl
 		;;
 	sso)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl-off"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl-off
 		;;
 	ssc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl-client"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl-client
 		;;
 	ssco)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl-client-off"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl-client-off
 		;;
 	css)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl
 		;;
 	cso)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl-off"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl-off
 		;;
 	csc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl-client"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl-client
 		;;
 	csco)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl-client-off"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl-client-off
 		;;
 	lss)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl
 		;;
 	lso)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl-off"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl-off
 		;;
 	lsc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl-client"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl-client
 		;;
 	lsco)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl-client-off"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl-client-off
 		;;
 	gmb|generate-multisite-bank)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS generate-multisite-bank $@"
+        # Pass remaining arguments ($@) correctly quoted to the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" generate-multisite-bank "$@"
 		;;
 	el)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS enable-ldap"
+		run_devtools_in_docker "${CONTAINER_ID}" enable-ldap
 		;;
 	dld)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS disable-ldap"
+		run_devtools_in_docker "${CONTAINER_ID}" disable-ldap
 		;;
 	xl)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS xdebug-log"
+		run_devtools_in_docker "${CONTAINER_ID}" xdebug-log
 		;;
 	lxp)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-xdebug-profiles"
+		run_devtools_in_docker "${CONTAINER_ID}" list-xdebug-profiles
 		;;
 	bad)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS build-api-docs"
+		run_devtools_in_docker "${CONTAINER_ID}" build-api-docs
 		;;
 	lm)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-multisites"
+		run_devtools_in_docker "${CONTAINER_ID}" list-multisites
 		;;
-
 	*)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS $FIRST_ARG"
+		# Default case: assume it's a devtools command
+		run_devtools_in_docker "${CONTAINER_ID}" "${FIRST_ARG}" "$@"
 		;;
 esac
-exit $FINAL_EXIT_CODE
+exit "${FINAL_EXIT_CODE}"
diff --git a/utilities/openemr-cmd/openemr-cmd-h b/utilities/openemr-cmd/openemr-cmd-h
index c8849aaf..e2fd29d1 100755
--- a/utilities/openemr-cmd/openemr-cmd-h
+++ b/utilities/openemr-cmd/openemr-cmd-h
@@ -1,13 +1,18 @@
 #!/bin/bash
-FIRST_ARG=$1
+
+set -euo pipefail # Exit on error, unset var, pipe failure
+
+FIRST_ARG="${1:-}" # Use parameter expansion default
 
 filter_help_output(){
-	FILTER_ARG=$1
-	LINE_COUNT=$2
-	openemr-cmd -h|grep $FILTER_ARG -A $LINE_COUNT
+	local FILTER_ARG="$1"
+	local LINE_COUNT="$2"
+	# Quoted variables
+	openemr-cmd -h | grep "${FILTER_ARG}" -A "${LINE_COUNT}"
 }
 
-if [ $# -eq 0 ]
+# Use (( )) for numeric comparisons
+if (( $# == 0 ))
 then
 	echo "To search the keyword from openemr-cmd -h output quickly
   Usage: openemr-cmd-h keyword
@@ -26,9 +31,11 @@ then
   webroot                   webroot-management
   others                    others
   keyword                   grep from openemr-cmd -h"
-	exit
+	exit 0 # Explicit success exit
 fi
-case "$FIRST_ARG" in
+
+# Use ${FIRST_ARG}
+case "${FIRST_ARG}" in
           docker)
 		filter_help_output docker-management 8
 		;;
@@ -42,7 +49,7 @@ case "$FIRST_ARG" in
 		filter_help_output sweep-management 2
 		;;
 	    reset)
-		filter_help_output reset-mamagement 4
+		filter_help_output reset-management 4
 		;;
 	    backup)
 		filter_help_output backup-management 6
@@ -69,5 +76,9 @@ case "$FIRST_ARG" in
 		openemr-cmd -h
 		;;
 		*)
-		openemr-cmd -h|grep -i $FIRST_ARG
+		# Quoted variable
+		openemr-cmd -h | grep -i "${FIRST_ARG}"
+		;;
 esac
+
+exit 0 # Explicit success exit at end of script


Reviews:
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T16:37:12Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T16:41:18Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T16:44:52Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T16:46:08Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T16:51:15Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T16:52:24Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T16:52:49Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T16:57:00Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T16:57:54Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T17:02:41Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T17:06:53Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T17:07:44Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T17:08:31Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T17:09:04Z
user: login: msummers42
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T18:08:04Z
user: login: msummers42
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T18:09:40Z
user: login: msummers42
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T18:19:22Z
user: login: msummers42
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T18:21:54Z
user: login: msummers42
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T18:24:06Z
user: login: msummers42
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T18:25:58Z
user: login: msummers42
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T18:30:43Z
user: login: kojiromike
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-24T18:47:32Z
user: login: msummers42
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-24T19:40:49Z

Review comments:
diff_hunk: @@ -1,16 +1,22 @@
 #!/bin/bash
+
+# Exit on error, unset var, pipe failure
+set -euo pipefail
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: Does anyone have thoughts about adding `-x` to this? I realize it can be noisy, but in my experience the only people who ever look at the output of a shell script actually want to know what's going on.
created_at: 2025-04-24T16:37:12Z
author_association: MEMBER
diff_hunk: @@ -24,267 +30,292 @@ get_container_names() {
 # Set the container names
 get_container_names
 
+# Function to run the devtools script inside the specified container
+# Usage: run_devtools_in_docker <container_id> <devtools_command> [args...]
+run_devtools_in_docker() {
+  local container_id="$1"
+  shift # Remove container_id from arguments
+  # DEV_TOOLS is '/root/devtools'
+  # "$@" passes the remaining arguments (devtools command and its args) correctly quoted
+  docker exec -i "${container_id}" "${DEV_TOOLS}" "$@"
+}
+
+# Function to run an arbitrary shell command string inside the specified container
+# Usage: run_shell_command_in_docker <container_id> <command_string>
+run_shell_command_in_docker() {
+  local container_id="$1"
+  local command_string="$2"
+  docker exec -i "${container_id}" sh -c "${command_string}"
+}
+
 # Set some constants
-DOCKER_EXEC_CMD='docker exec -i'                                 # docker exec command
-SHELL_TYPE='sh -c'                                               # specify shell type
-FIRST_ARG=$1											                               # define the first parameter
-DEV_TOOLS=/root/devtools
+FIRST_ARG="${1:-}" # define the first parameter, default to empty if not set
+DEV_TOOLS='/root/devtools'
 
 check_docker_compose_install_or_not(){
-	DOCKER_COMPOSE_CODE=22
-	which docker-compose &>/dev/null
-	[ $? -ne 0 ] && echo "Please check docker-compose install or not." && exit $DOCKER_COMPOSE_CODE
+	local DOCKER_COMPOSE_CODE=22
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: I'll make a PR to bring the .editorconfig from openemr/openemr over so we can start to try to avoid mixing tabs and spaces, and other stuff.
created_at: 2025-04-24T16:41:18Z
author_association: MEMBER
diff_hunk: @@ -24,267 +30,292 @@ get_container_names() {
 # Set the container names
 get_container_names
 
+# Function to run the devtools script inside the specified container
+# Usage: run_devtools_in_docker <container_id> <devtools_command> [args...]
+run_devtools_in_docker() {
+  local container_id="$1"
+  shift # Remove container_id from arguments
+  # DEV_TOOLS is '/root/devtools'
+  # "$@" passes the remaining arguments (devtools command and its args) correctly quoted
+  docker exec -i "${container_id}" "${DEV_TOOLS}" "$@"
+}
+
+# Function to run an arbitrary shell command string inside the specified container
+# Usage: run_shell_command_in_docker <container_id> <command_string>
+run_shell_command_in_docker() {
+  local container_id="$1"
+  local command_string="$2"
+  docker exec -i "${container_id}" sh -c "${command_string}"
+}
+
 # Set some constants
-DOCKER_EXEC_CMD='docker exec -i'                                 # docker exec command
-SHELL_TYPE='sh -c'                                               # specify shell type
-FIRST_ARG=$1											                               # define the first parameter
-DEV_TOOLS=/root/devtools
+FIRST_ARG="${1:-}" # define the first parameter, default to empty if not set
+DEV_TOOLS='/root/devtools'
 
 check_docker_compose_install_or_not(){
-	DOCKER_COMPOSE_CODE=22
-	which docker-compose &>/dev/null
-	[ $? -ne 0 ] && echo "Please check docker-compose install or not." && exit $DOCKER_COMPOSE_CODE
+	local DOCKER_COMPOSE_CODE=22
+	if ! command -v docker-compose &>/dev/null; then
+		echo "Please check docker-compose install or not."
+    exit "${DOCKER_COMPOSE_CODE}"
+	fi
 }
 
 quick_open_a_docker_shell(){
-  docker exec -w /var/www/localhost/htdocs/openemr -it $CONTAINER_ID sh
+  docker exec -w /var/www/localhost/htdocs/openemr -it "${CONTAINER_ID}" sh
 }
 
 quick_open_a_maria_docker_shell(){
-  docker exec -it $MARIADB_CONTAINER_ID /bin/bash
+  docker exec -it "${MARIADB_CONTAINER_ID}" /bin/bash
 }
 
 execute_command_flexible(){
-	if [ $# -lt 1 ]
-	then
+	if [[ $# -lt 1 ]]; then
 		echo "Please provide the command."
-		echo "e.g. `basename $0` [exec|e] \"tail -f /var/log/apache2/error.log\""
-		echo "e.g. `basename $0` -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$@"
+		# Use the function for arbitrary commands
+		run_shell_command_in_docker "${CONTAINER_ID}" "$@"
 	fi
 }
 
 check_docker_log() {
-  docker logs $CONTAINER_ID
+  docker logs "${CONTAINER_ID}"
 }
 
 check_docker_names() {
-	CHECK_NAME=$1     # specify the checking name
-	if [ $# -eq 1 ]
-	then
+	if [[ $# -eq 1 ]]; then
 		# ARGS: couchdb php fhir mariadb mysql nginx openemr openldap orthanc redis.
+        # specify the name to check
+        local CHECK_NAME="$1"
 		echo '===Check the single Docker Name==='
 		echo '  STATUS        NAME'
-		docker ps -a --format "{{.Status}}\t{{.Names}}"| grep $CHECK_NAME
+        # Capture output, check if empty
+        local matching_container
+        matching_container=$(docker ps -a --format "{{.Status}}\t{{.Names}}"| grep "${CHECK_NAME}" || true) # Keep || true here, and below, to prevent exit during capture
+        if [[ -z "${matching_container}" ]]; then
+            echo "No containers found matching '${CHECK_NAME}'"
+        else
+            echo "${matching_container}"
+        fi
 
 	else
 		# Show all the docker names.
 		echo '***************************************************************'
 		echo 'Show all the docker names by default.'
 		echo 'Please provide the keyword if you want to check the single one.'
-		echo "e.g `basename $0` [docker-names|dn] php"
+		echo "e.g $(basename "$0") [docker-names|dn] php"
 		echo '***************************************************************'
 		echo '=======Running Docker Names======='
-		docker ps | awk '{print $NF}'|grep -v NAMES|sort -n
+		
+        # Capture output, check if empty
+        local running_containers
+        running_containers=$(docker ps --format "{{.Status}}\t{{.Names}}" | { grep -v NAMES || true; } | sort -n)
+        if [[ -z "${running_containers}" ]]; then
+            echo "No running containers found."
+        else
+		    echo '  STATUS        NAME'
+            echo "${running_containers}"
+        fi
 		echo '====Other Docker Status Names====='
-		docker ps -a --format "table{{.Status}}\t{{.Names}}"| grep -v Up
+        # Capture output, check if empty
+        local other_containers
+        other_containers=$(docker ps -a --format "{{.Status}}\t{{.Names}}" | grep -v Up || true)
+        if [[ -z "${other_containers}" ]]; then
+            echo "No containers found with other statuses."
+        else
+		    echo '  STATUS        NAME'
+            echo "${other_containers}"
+        fi
 	fi
 }
 
 restart_couchdb_docker(){
-  if [ -z "$COUCHDB_CONTAINER" ]
-  then
+  if [[ -z "${COUCHDB_CONTAINER}" ]]; then
     echo "Unable to find the couchdb docker, so could not restart it"
   else
     echo "Restarting couchdb docker"
-    docker restart "$COUCHDB_CONTAINER"
+    docker restart "${COUCHDB_CONTAINER}"
   fi
 }
 
 creat_a_backup_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=20
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=20
+    if [[ $# != 1 ]]; then
 		echo 'Please provide a snapshot name.'
 		echo 'e.g. openemr-cmd [backup-snapshot|bs] example'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS backup $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" backup "${BACKUP_FILE}"
 	fi
 }
 
 restore_from_a_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=21
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=21
+    if [[ $# != 1 ]]; then
         echo 'Please provide a restore snapshot name.'
         echo 'e.g. openemr-cmd [restore-snapshot|rs] example'
-        exit $BACKUP_FILE_CODE
+        exit "${BACKUP_FILE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS restore $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" restore "${BACKUP_FILE}"
 	fi
 }
 
 copy_capsule_from_docker_to_host(){
-	BACKUP_FILE=$1
-	BACKUP_HOST_DIR=$2 #optional parameter
-	BACKUP_FILE_CODE=19
-	if [ $# != 1 ] && [ $# != 2 ]
-	then
+	local BACKUP_FILE="$1"
+	local BACKUP_HOST_DIR="${2:-}" #optional parameter, default to empty
+	local BACKUP_FILE_CODE=19
+	if [[ $# != 1 ]] && [[ $# != 2 ]]; then
 		echo 'Please provide the capsule name.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz'
 		echo 'An optional setting is the path to save to. If nothing provided, then will save in current directory.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz /path/to/save'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-	  if [ -z "$BACKUP_HOST_DIR" ]
-	  then
-		  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE .
+	  if [[ -z "${BACKUP_HOST_DIR}" ]]; then
+		  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" .
     else
-      	  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE "${BACKUP_HOST_DIR}/"
+      	  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" "${BACKUP_HOST_DIR}/"
     fi
 	fi
 }
 
 copy_capsule_from_host_to_docker(){
 	# Need a capsule parameter
-	BACKUP_FILE=$1
-	CP_CAP_DIR_DKR_CODE=15
-	BACKUP_FILE_CODE=18
-	if [ $# != 1 ]
-	then
+	local BACKUP_FILE="$1"
+	local CP_CAP_DIR_DKR_CODE=15
+	local BACKUP_FILE_CODE=18
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the capsule file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [put-capsule|pc] example.tgz'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		ls $BACKUP_FILE  &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${BACKUP_FILE}" &>/dev/null; then
 			echo 'Please check whether the capsule file exists or not'
-			exit $CP_CAP_DIR_DKR_CODE
+			exit "${CP_CAP_DIR_DKR_CODE}"
 		else
-			docker cp $BACKUP_FILE  ${CONTAINER_ID}:/snapshots/
+			docker cp "${BACKUP_FILE}" "${CONTAINER_ID}:/snapshots/"
 		fi
 	fi
 }
 
 ensure_current_ver_with_upgrade_ver(){
   # Need a version parameter
-  UPGRADE_FROM_VERSION=$1
-  BACKUP_FILE_CODE=22
-	if [ $# != 1 ]
-	then
+  local UPGRADE_FROM_VERSION="$1"
+  local BACKUP_FILE_CODE=22
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the OpenEMR version to upgrade database from.'
 		echo 'e.g. openemr-cmd [ensure-version|ev] 5.0.2'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS upgrade ${UPGRADE_FROM_VERSION}"
+    # Use the devtools function
+    run_devtools_in_docker "${CONTAINER_ID}" upgrade "${UPGRADE_FROM_VERSION}"
 	fi
 }
 
 change_db_character_set_and_collation(){
-	CHARACTER_SET_COLLATION_CODE=17
-	if [ $# != 2 ]
-	then
+	local CHARACTER_SET_COLLATION_CODE=17
+	if [[ $# != 2 ]]; then
 		echo 'Please provide two parameters.'
 		echo 'e.g. openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_general_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_unicode_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_vietnamese_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8 utf8_general_ci'
-		exit $CHARACTER_SET_COLLATION_CODE
+		exit "${CHARACTER_SET_COLLATION_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS change-encoding-collation $1 $2"
+		# Use the devtools function, passing both arguments
+		run_devtools_in_docker "${CONTAINER_ID}" change-encoding-collation "$1" "$2"
 	fi
 }
 
 setup-client-cert(){
-    CERT_PACKAGE=$1
-    CERT_PACKAGE_CODE=30
-    if [ $# != 1 ]
-    then
+    local CERT_PACKAGE="$1"
+    local CERT_PACKAGE_CODE=30
+    if [[ $# != 1 ]]; then
         echo 'Please provide a certificate package name.'
         echo 'e.g. openemr-cmd [scc|setup-client-cert] sll'
-        exit $CERT_PACKAGE_CODE
+        exit "${CERT_PACKAGE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS setup-client-cert $CERT_PACKAGE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" setup-client-cert "${CERT_PACKAGE}"
 	fi
 }
 
 put-client-cert(){
 	# Need a capsule parameter
-	CERT_PACKAGE_FILE=$1
-	PUT_CLIENT_CERT_CODE=32
-	CERT_PACKAGE_FILE_CODE=31
-	if [ $# != 1 ]
-	then
+	local CERT_PACKAGE_FILE="$1"
+	local PUT_CLIENT_CERT_CODE=32
+	local CERT_PACKAGE_FILE_CODE=31
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the certificate package file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [pcc|put-client-cert] sll.zip'
-		exit $CERT_PACKAGE_FILE_CODE
+		exit "${CERT_PACKAGE_FILE_CODE}"
 	else
-		ls $CERT_PACKAGE_FILE &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${CERT_PACKAGE_FILE}" &>/dev/null; then
 			echo 'Please check whether the certificate package file exists or not'
-			exit $PUT_CLIENT_CERT_CODE
+			exit "${PUT_CLIENT_CERT_CODE}"
 		else
-			docker cp $CERT_PACKAGE_FILE ${CONTAINER_ID}:/certs/
+			docker cp "${CERT_PACKAGE_FILE}" "${CONTAINER_ID}:/certs/"
 		fi
 	fi
 }
 
 import-random-patients(){
-  if [ $# == 2 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1 $2"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" import-random-patients "$@"
 }
 
 register-oauth2-client-demo(){
-  $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client-demo $1"
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client-demo "$@"
 }
 
 register-oauth2-client(){
-  if [ $# == 1 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client $1"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client "$@"
 }
 
 set-swagger-to-multisite(){
-    if [ $# == 1 ]
-    then
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite $1"
-    else
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite"
-    fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" set-swagger-to-multisite "$@"
 }
 
 set-webroot(){
-    if [ $# == 1 ]
-    then
+    local sed_command
+    if [[ $# == 1 ]]; then
       # assume the openemr parameter was given, so set openemr webroot
       echo "changing webroot to openemr"
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs@g' /etc/apache2/conf.d/openemr.conf"
+      sed_command="sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs@g' /etc/apache2/conf.d/openemr.conf"
     else
       # set to blank, so set blank webroot
       echo "changing webroot to blank"
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs/openemr@g' /etc/apache2/conf.d/openemr.conf"
+      sed_command="sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs/openemr@g' /etc/apache2/conf.d/openemr.conf"
     fi
+    # Use the function for arbitrary commands
+    run_shell_command_in_docker "${CONTAINER_ID}" "${sed_command}"
     # restart the docker
     echo "restarting openemr docker so the apache configuration change will take effect"
-    docker restart "$CONTAINER_ID"
+    docker restart "${CONTAINER_ID}"
 }
 
 docker-pull-image(){
+    local docker_images
     docker_images=$(docker ps --format "table {{.Image}}")
-    for IMAGE in $docker_images
-    do
-    if [ $IMAGE != "IMAGE" ] 
-    then
-      read -e -p "Do you wish to pull $IMAGE ? (y) " RESP
-      if [ "$RESP" = "y" ]; then 
-        docker pull "$IMAGE";
-      else 
-        echo "Skipping $IMAGE";
+    local IMAGE RESP
+    for IMAGE in ${docker_images}; do
+      if [[ "${IMAGE}" != "IMAGE" ]]; then
+        # Use -r with read
+        read -r -e -p "Do you wish to pull ${IMAGE} ? (y) " RESP
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: why `-e`, I wonder. Using readline could be useful if you wanted to enable history navigation, inline editing or tab completion, for example, but this is just a `y` or not.
created_at: 2025-04-24T16:44:52Z
author_association: MEMBER
diff_hunk: @@ -24,267 +30,292 @@ get_container_names() {
 # Set the container names
 get_container_names
 
+# Function to run the devtools script inside the specified container
+# Usage: run_devtools_in_docker <container_id> <devtools_command> [args...]
+run_devtools_in_docker() {
+  local container_id="$1"
+  shift # Remove container_id from arguments
+  # DEV_TOOLS is '/root/devtools'
+  # "$@" passes the remaining arguments (devtools command and its args) correctly quoted
+  docker exec -i "${container_id}" "${DEV_TOOLS}" "$@"
+}
+
+# Function to run an arbitrary shell command string inside the specified container
+# Usage: run_shell_command_in_docker <container_id> <command_string>
+run_shell_command_in_docker() {
+  local container_id="$1"
+  local command_string="$2"
+  docker exec -i "${container_id}" sh -c "${command_string}"
+}
+
 # Set some constants
-DOCKER_EXEC_CMD='docker exec -i'                                 # docker exec command
-SHELL_TYPE='sh -c'                                               # specify shell type
-FIRST_ARG=$1											                               # define the first parameter
-DEV_TOOLS=/root/devtools
+FIRST_ARG="${1:-}" # define the first parameter, default to empty if not set
+DEV_TOOLS='/root/devtools'
 
 check_docker_compose_install_or_not(){
-	DOCKER_COMPOSE_CODE=22
-	which docker-compose &>/dev/null
-	[ $? -ne 0 ] && echo "Please check docker-compose install or not." && exit $DOCKER_COMPOSE_CODE
+	local DOCKER_COMPOSE_CODE=22
+	if ! command -v docker-compose &>/dev/null; then
+		echo "Please check docker-compose install or not."
+    exit "${DOCKER_COMPOSE_CODE}"
+	fi
 }
 
 quick_open_a_docker_shell(){
-  docker exec -w /var/www/localhost/htdocs/openemr -it $CONTAINER_ID sh
+  docker exec -w /var/www/localhost/htdocs/openemr -it "${CONTAINER_ID}" sh
 }
 
 quick_open_a_maria_docker_shell(){
-  docker exec -it $MARIADB_CONTAINER_ID /bin/bash
+  docker exec -it "${MARIADB_CONTAINER_ID}" /bin/bash
 }
 
 execute_command_flexible(){
-	if [ $# -lt 1 ]
-	then
+	if [[ $# -lt 1 ]]; then
 		echo "Please provide the command."
-		echo "e.g. `basename $0` [exec|e] \"tail -f /var/log/apache2/error.log\""
-		echo "e.g. `basename $0` -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$@"
+		# Use the function for arbitrary commands
+		run_shell_command_in_docker "${CONTAINER_ID}" "$@"
 	fi
 }
 
 check_docker_log() {
-  docker logs $CONTAINER_ID
+  docker logs "${CONTAINER_ID}"
 }
 
 check_docker_names() {
-	CHECK_NAME=$1     # specify the checking name
-	if [ $# -eq 1 ]
-	then
+	if [[ $# -eq 1 ]]; then
 		# ARGS: couchdb php fhir mariadb mysql nginx openemr openldap orthanc redis.
+        # specify the name to check
+        local CHECK_NAME="$1"
 		echo '===Check the single Docker Name==='
 		echo '  STATUS        NAME'
-		docker ps -a --format "{{.Status}}\t{{.Names}}"| grep $CHECK_NAME
+        # Capture output, check if empty
+        local matching_container
+        matching_container=$(docker ps -a --format "{{.Status}}\t{{.Names}}"| grep "${CHECK_NAME}" || true) # Keep || true here, and below, to prevent exit during capture
+        if [[ -z "${matching_container}" ]]; then
+            echo "No containers found matching '${CHECK_NAME}'"
+        else
+            echo "${matching_container}"
+        fi
 
 	else
 		# Show all the docker names.
 		echo '***************************************************************'
 		echo 'Show all the docker names by default.'
 		echo 'Please provide the keyword if you want to check the single one.'
-		echo "e.g `basename $0` [docker-names|dn] php"
+		echo "e.g $(basename "$0") [docker-names|dn] php"
 		echo '***************************************************************'
 		echo '=======Running Docker Names======='
-		docker ps | awk '{print $NF}'|grep -v NAMES|sort -n
+		
+        # Capture output, check if empty
+        local running_containers
+        running_containers=$(docker ps --format "{{.Status}}\t{{.Names}}" | { grep -v NAMES || true; } | sort -n)
+        if [[ -z "${running_containers}" ]]; then
+            echo "No running containers found."
+        else
+		    echo '  STATUS        NAME'
+            echo "${running_containers}"
+        fi
 		echo '====Other Docker Status Names====='
-		docker ps -a --format "table{{.Status}}\t{{.Names}}"| grep -v Up
+        # Capture output, check if empty
+        local other_containers
+        other_containers=$(docker ps -a --format "{{.Status}}\t{{.Names}}" | grep -v Up || true)
+        if [[ -z "${other_containers}" ]]; then
+            echo "No containers found with other statuses."
+        else
+		    echo '  STATUS        NAME'
+            echo "${other_containers}"
+        fi
 	fi
 }
 
 restart_couchdb_docker(){
-  if [ -z "$COUCHDB_CONTAINER" ]
-  then
+  if [[ -z "${COUCHDB_CONTAINER}" ]]; then
     echo "Unable to find the couchdb docker, so could not restart it"
   else
     echo "Restarting couchdb docker"
-    docker restart "$COUCHDB_CONTAINER"
+    docker restart "${COUCHDB_CONTAINER}"
   fi
 }
 
 creat_a_backup_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=20
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=20
+    if [[ $# != 1 ]]; then
 		echo 'Please provide a snapshot name.'
 		echo 'e.g. openemr-cmd [backup-snapshot|bs] example'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS backup $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" backup "${BACKUP_FILE}"
 	fi
 }
 
 restore_from_a_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=21
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=21
+    if [[ $# != 1 ]]; then
         echo 'Please provide a restore snapshot name.'
         echo 'e.g. openemr-cmd [restore-snapshot|rs] example'
-        exit $BACKUP_FILE_CODE
+        exit "${BACKUP_FILE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS restore $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" restore "${BACKUP_FILE}"
 	fi
 }
 
 copy_capsule_from_docker_to_host(){
-	BACKUP_FILE=$1
-	BACKUP_HOST_DIR=$2 #optional parameter
-	BACKUP_FILE_CODE=19
-	if [ $# != 1 ] && [ $# != 2 ]
-	then
+	local BACKUP_FILE="$1"
+	local BACKUP_HOST_DIR="${2:-}" #optional parameter, default to empty
+	local BACKUP_FILE_CODE=19
+	if [[ $# != 1 ]] && [[ $# != 2 ]]; then
 		echo 'Please provide the capsule name.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz'
 		echo 'An optional setting is the path to save to. If nothing provided, then will save in current directory.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz /path/to/save'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-	  if [ -z "$BACKUP_HOST_DIR" ]
-	  then
-		  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE .
+	  if [[ -z "${BACKUP_HOST_DIR}" ]]; then
+		  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" .
     else
-      	  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE "${BACKUP_HOST_DIR}/"
+      	  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" "${BACKUP_HOST_DIR}/"
     fi
 	fi
 }
 
 copy_capsule_from_host_to_docker(){
 	# Need a capsule parameter
-	BACKUP_FILE=$1
-	CP_CAP_DIR_DKR_CODE=15
-	BACKUP_FILE_CODE=18
-	if [ $# != 1 ]
-	then
+	local BACKUP_FILE="$1"
+	local CP_CAP_DIR_DKR_CODE=15
+	local BACKUP_FILE_CODE=18
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the capsule file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [put-capsule|pc] example.tgz'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		ls $BACKUP_FILE  &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${BACKUP_FILE}" &>/dev/null; then
 			echo 'Please check whether the capsule file exists or not'
-			exit $CP_CAP_DIR_DKR_CODE
+			exit "${CP_CAP_DIR_DKR_CODE}"
 		else
-			docker cp $BACKUP_FILE  ${CONTAINER_ID}:/snapshots/
+			docker cp "${BACKUP_FILE}" "${CONTAINER_ID}:/snapshots/"
 		fi
 	fi
 }
 
 ensure_current_ver_with_upgrade_ver(){
   # Need a version parameter
-  UPGRADE_FROM_VERSION=$1
-  BACKUP_FILE_CODE=22
-	if [ $# != 1 ]
-	then
+  local UPGRADE_FROM_VERSION="$1"
+  local BACKUP_FILE_CODE=22
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the OpenEMR version to upgrade database from.'
 		echo 'e.g. openemr-cmd [ensure-version|ev] 5.0.2'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS upgrade ${UPGRADE_FROM_VERSION}"
+    # Use the devtools function
+    run_devtools_in_docker "${CONTAINER_ID}" upgrade "${UPGRADE_FROM_VERSION}"
 	fi
 }
 
 change_db_character_set_and_collation(){
-	CHARACTER_SET_COLLATION_CODE=17
-	if [ $# != 2 ]
-	then
+	local CHARACTER_SET_COLLATION_CODE=17
+	if [[ $# != 2 ]]; then
 		echo 'Please provide two parameters.'
 		echo 'e.g. openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_general_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_unicode_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_vietnamese_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8 utf8_general_ci'
-		exit $CHARACTER_SET_COLLATION_CODE
+		exit "${CHARACTER_SET_COLLATION_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS change-encoding-collation $1 $2"
+		# Use the devtools function, passing both arguments
+		run_devtools_in_docker "${CONTAINER_ID}" change-encoding-collation "$1" "$2"
 	fi
 }
 
 setup-client-cert(){
-    CERT_PACKAGE=$1
-    CERT_PACKAGE_CODE=30
-    if [ $# != 1 ]
-    then
+    local CERT_PACKAGE="$1"
+    local CERT_PACKAGE_CODE=30
+    if [[ $# != 1 ]]; then
         echo 'Please provide a certificate package name.'
         echo 'e.g. openemr-cmd [scc|setup-client-cert] sll'
-        exit $CERT_PACKAGE_CODE
+        exit "${CERT_PACKAGE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS setup-client-cert $CERT_PACKAGE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" setup-client-cert "${CERT_PACKAGE}"
 	fi
 }
 
 put-client-cert(){
 	# Need a capsule parameter
-	CERT_PACKAGE_FILE=$1
-	PUT_CLIENT_CERT_CODE=32
-	CERT_PACKAGE_FILE_CODE=31
-	if [ $# != 1 ]
-	then
+	local CERT_PACKAGE_FILE="$1"
+	local PUT_CLIENT_CERT_CODE=32
+	local CERT_PACKAGE_FILE_CODE=31
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the certificate package file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [pcc|put-client-cert] sll.zip'
-		exit $CERT_PACKAGE_FILE_CODE
+		exit "${CERT_PACKAGE_FILE_CODE}"
 	else
-		ls $CERT_PACKAGE_FILE &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${CERT_PACKAGE_FILE}" &>/dev/null; then
 			echo 'Please check whether the certificate package file exists or not'
-			exit $PUT_CLIENT_CERT_CODE
+			exit "${PUT_CLIENT_CERT_CODE}"
 		else
-			docker cp $CERT_PACKAGE_FILE ${CONTAINER_ID}:/certs/
+			docker cp "${CERT_PACKAGE_FILE}" "${CONTAINER_ID}:/certs/"
 		fi
 	fi
 }
 
 import-random-patients(){
-  if [ $# == 2 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1 $2"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" import-random-patients "$@"
 }
 
 register-oauth2-client-demo(){
-  $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client-demo $1"
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client-demo "$@"
 }
 
 register-oauth2-client(){
-  if [ $# == 1 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client $1"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client "$@"
 }
 
 set-swagger-to-multisite(){
-    if [ $# == 1 ]
-    then
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite $1"
-    else
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite"
-    fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" set-swagger-to-multisite "$@"
 }
 
 set-webroot(){
-    if [ $# == 1 ]
-    then
+    local sed_command
+    if [[ $# == 1 ]]; then
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: Suggest using arithmetic context for a pure arithmetic check

```suggestion
    if (( $# == 1 )); then
```
created_at: 2025-04-24T16:46:07Z
author_association: MEMBER
diff_hunk: @@ -24,267 +30,292 @@ get_container_names() {
 # Set the container names
 get_container_names
 
+# Function to run the devtools script inside the specified container
+# Usage: run_devtools_in_docker <container_id> <devtools_command> [args...]
+run_devtools_in_docker() {
+  local container_id="$1"
+  shift # Remove container_id from arguments
+  # DEV_TOOLS is '/root/devtools'
+  # "$@" passes the remaining arguments (devtools command and its args) correctly quoted
+  docker exec -i "${container_id}" "${DEV_TOOLS}" "$@"
+}
+
+# Function to run an arbitrary shell command string inside the specified container
+# Usage: run_shell_command_in_docker <container_id> <command_string>
+run_shell_command_in_docker() {
+  local container_id="$1"
+  local command_string="$2"
+  docker exec -i "${container_id}" sh -c "${command_string}"
+}
+
 # Set some constants
-DOCKER_EXEC_CMD='docker exec -i'                                 # docker exec command
-SHELL_TYPE='sh -c'                                               # specify shell type
-FIRST_ARG=$1											                               # define the first parameter
-DEV_TOOLS=/root/devtools
+FIRST_ARG="${1:-}" # define the first parameter, default to empty if not set
+DEV_TOOLS='/root/devtools'
 
 check_docker_compose_install_or_not(){
-	DOCKER_COMPOSE_CODE=22
-	which docker-compose &>/dev/null
-	[ $? -ne 0 ] && echo "Please check docker-compose install or not." && exit $DOCKER_COMPOSE_CODE
+	local DOCKER_COMPOSE_CODE=22
+	if ! command -v docker-compose &>/dev/null; then
+		echo "Please check docker-compose install or not."
+    exit "${DOCKER_COMPOSE_CODE}"
+	fi
 }
 
 quick_open_a_docker_shell(){
-  docker exec -w /var/www/localhost/htdocs/openemr -it $CONTAINER_ID sh
+  docker exec -w /var/www/localhost/htdocs/openemr -it "${CONTAINER_ID}" sh
 }
 
 quick_open_a_maria_docker_shell(){
-  docker exec -it $MARIADB_CONTAINER_ID /bin/bash
+  docker exec -it "${MARIADB_CONTAINER_ID}" /bin/bash
 }
 
 execute_command_flexible(){
-	if [ $# -lt 1 ]
-	then
+	if [[ $# -lt 1 ]]; then
 		echo "Please provide the command."
-		echo "e.g. `basename $0` [exec|e] \"tail -f /var/log/apache2/error.log\""
-		echo "e.g. `basename $0` -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$@"
+		# Use the function for arbitrary commands
+		run_shell_command_in_docker "${CONTAINER_ID}" "$@"
 	fi
 }
 
 check_docker_log() {
-  docker logs $CONTAINER_ID
+  docker logs "${CONTAINER_ID}"
 }
 
 check_docker_names() {
-	CHECK_NAME=$1     # specify the checking name
-	if [ $# -eq 1 ]
-	then
+	if [[ $# -eq 1 ]]; then
 		# ARGS: couchdb php fhir mariadb mysql nginx openemr openldap orthanc redis.
+        # specify the name to check
+        local CHECK_NAME="$1"
 		echo '===Check the single Docker Name==='
 		echo '  STATUS        NAME'
-		docker ps -a --format "{{.Status}}\t{{.Names}}"| grep $CHECK_NAME
+        # Capture output, check if empty
+        local matching_container
+        matching_container=$(docker ps -a --format "{{.Status}}\t{{.Names}}"| grep "${CHECK_NAME}" || true) # Keep || true here, and below, to prevent exit during capture
+        if [[ -z "${matching_container}" ]]; then
+            echo "No containers found matching '${CHECK_NAME}'"
+        else
+            echo "${matching_container}"
+        fi
 
 	else
 		# Show all the docker names.
 		echo '***************************************************************'
 		echo 'Show all the docker names by default.'
 		echo 'Please provide the keyword if you want to check the single one.'
-		echo "e.g `basename $0` [docker-names|dn] php"
+		echo "e.g $(basename "$0") [docker-names|dn] php"
 		echo '***************************************************************'
 		echo '=======Running Docker Names======='
-		docker ps | awk '{print $NF}'|grep -v NAMES|sort -n
+		
+        # Capture output, check if empty
+        local running_containers
+        running_containers=$(docker ps --format "{{.Status}}\t{{.Names}}" | { grep -v NAMES || true; } | sort -n)
+        if [[ -z "${running_containers}" ]]; then
+            echo "No running containers found."
+        else
+		    echo '  STATUS        NAME'
+            echo "${running_containers}"
+        fi
 		echo '====Other Docker Status Names====='
-		docker ps -a --format "table{{.Status}}\t{{.Names}}"| grep -v Up
+        # Capture output, check if empty
+        local other_containers
+        other_containers=$(docker ps -a --format "{{.Status}}\t{{.Names}}" | grep -v Up || true)
+        if [[ -z "${other_containers}" ]]; then
+            echo "No containers found with other statuses."
+        else
+		    echo '  STATUS        NAME'
+            echo "${other_containers}"
+        fi
 	fi
 }
 
 restart_couchdb_docker(){
-  if [ -z "$COUCHDB_CONTAINER" ]
-  then
+  if [[ -z "${COUCHDB_CONTAINER}" ]]; then
     echo "Unable to find the couchdb docker, so could not restart it"
   else
     echo "Restarting couchdb docker"
-    docker restart "$COUCHDB_CONTAINER"
+    docker restart "${COUCHDB_CONTAINER}"
   fi
 }
 
 creat_a_backup_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=20
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=20
+    if [[ $# != 1 ]]; then
 		echo 'Please provide a snapshot name.'
 		echo 'e.g. openemr-cmd [backup-snapshot|bs] example'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS backup $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" backup "${BACKUP_FILE}"
 	fi
 }
 
 restore_from_a_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=21
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=21
+    if [[ $# != 1 ]]; then
         echo 'Please provide a restore snapshot name.'
         echo 'e.g. openemr-cmd [restore-snapshot|rs] example'
-        exit $BACKUP_FILE_CODE
+        exit "${BACKUP_FILE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS restore $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" restore "${BACKUP_FILE}"
 	fi
 }
 
 copy_capsule_from_docker_to_host(){
-	BACKUP_FILE=$1
-	BACKUP_HOST_DIR=$2 #optional parameter
-	BACKUP_FILE_CODE=19
-	if [ $# != 1 ] && [ $# != 2 ]
-	then
+	local BACKUP_FILE="$1"
+	local BACKUP_HOST_DIR="${2:-}" #optional parameter, default to empty
+	local BACKUP_FILE_CODE=19
+	if [[ $# != 1 ]] && [[ $# != 2 ]]; then
 		echo 'Please provide the capsule name.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz'
 		echo 'An optional setting is the path to save to. If nothing provided, then will save in current directory.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz /path/to/save'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-	  if [ -z "$BACKUP_HOST_DIR" ]
-	  then
-		  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE .
+	  if [[ -z "${BACKUP_HOST_DIR}" ]]; then
+		  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" .
     else
-      	  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE "${BACKUP_HOST_DIR}/"
+      	  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" "${BACKUP_HOST_DIR}/"
     fi
 	fi
 }
 
 copy_capsule_from_host_to_docker(){
 	# Need a capsule parameter
-	BACKUP_FILE=$1
-	CP_CAP_DIR_DKR_CODE=15
-	BACKUP_FILE_CODE=18
-	if [ $# != 1 ]
-	then
+	local BACKUP_FILE="$1"
+	local CP_CAP_DIR_DKR_CODE=15
+	local BACKUP_FILE_CODE=18
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the capsule file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [put-capsule|pc] example.tgz'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		ls $BACKUP_FILE  &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${BACKUP_FILE}" &>/dev/null; then
 			echo 'Please check whether the capsule file exists or not'
-			exit $CP_CAP_DIR_DKR_CODE
+			exit "${CP_CAP_DIR_DKR_CODE}"
 		else
-			docker cp $BACKUP_FILE  ${CONTAINER_ID}:/snapshots/
+			docker cp "${BACKUP_FILE}" "${CONTAINER_ID}:/snapshots/"
 		fi
 	fi
 }
 
 ensure_current_ver_with_upgrade_ver(){
   # Need a version parameter
-  UPGRADE_FROM_VERSION=$1
-  BACKUP_FILE_CODE=22
-	if [ $# != 1 ]
-	then
+  local UPGRADE_FROM_VERSION="$1"
+  local BACKUP_FILE_CODE=22
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the OpenEMR version to upgrade database from.'
 		echo 'e.g. openemr-cmd [ensure-version|ev] 5.0.2'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS upgrade ${UPGRADE_FROM_VERSION}"
+    # Use the devtools function
+    run_devtools_in_docker "${CONTAINER_ID}" upgrade "${UPGRADE_FROM_VERSION}"
 	fi
 }
 
 change_db_character_set_and_collation(){
-	CHARACTER_SET_COLLATION_CODE=17
-	if [ $# != 2 ]
-	then
+	local CHARACTER_SET_COLLATION_CODE=17
+	if [[ $# != 2 ]]; then
 		echo 'Please provide two parameters.'
 		echo 'e.g. openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_general_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_unicode_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_vietnamese_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8 utf8_general_ci'
-		exit $CHARACTER_SET_COLLATION_CODE
+		exit "${CHARACTER_SET_COLLATION_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS change-encoding-collation $1 $2"
+		# Use the devtools function, passing both arguments
+		run_devtools_in_docker "${CONTAINER_ID}" change-encoding-collation "$1" "$2"
 	fi
 }
 
 setup-client-cert(){
-    CERT_PACKAGE=$1
-    CERT_PACKAGE_CODE=30
-    if [ $# != 1 ]
-    then
+    local CERT_PACKAGE="$1"
+    local CERT_PACKAGE_CODE=30
+    if [[ $# != 1 ]]; then
         echo 'Please provide a certificate package name.'
         echo 'e.g. openemr-cmd [scc|setup-client-cert] sll'
-        exit $CERT_PACKAGE_CODE
+        exit "${CERT_PACKAGE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS setup-client-cert $CERT_PACKAGE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" setup-client-cert "${CERT_PACKAGE}"
 	fi
 }
 
 put-client-cert(){
 	# Need a capsule parameter
-	CERT_PACKAGE_FILE=$1
-	PUT_CLIENT_CERT_CODE=32
-	CERT_PACKAGE_FILE_CODE=31
-	if [ $# != 1 ]
-	then
+	local CERT_PACKAGE_FILE="$1"
+	local PUT_CLIENT_CERT_CODE=32
+	local CERT_PACKAGE_FILE_CODE=31
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the certificate package file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [pcc|put-client-cert] sll.zip'
-		exit $CERT_PACKAGE_FILE_CODE
+		exit "${CERT_PACKAGE_FILE_CODE}"
 	else
-		ls $CERT_PACKAGE_FILE &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${CERT_PACKAGE_FILE}" &>/dev/null; then
 			echo 'Please check whether the certificate package file exists or not'
-			exit $PUT_CLIENT_CERT_CODE
+			exit "${PUT_CLIENT_CERT_CODE}"
 		else
-			docker cp $CERT_PACKAGE_FILE ${CONTAINER_ID}:/certs/
+			docker cp "${CERT_PACKAGE_FILE}" "${CONTAINER_ID}:/certs/"
 		fi
 	fi
 }
 
 import-random-patients(){
-  if [ $# == 2 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1 $2"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" import-random-patients "$@"
 }
 
 register-oauth2-client-demo(){
-  $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client-demo $1"
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client-demo "$@"
 }
 
 register-oauth2-client(){
-  if [ $# == 1 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client $1"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client "$@"
 }
 
 set-swagger-to-multisite(){
-    if [ $# == 1 ]
-    then
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite $1"
-    else
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite"
-    fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" set-swagger-to-multisite "$@"
 }
 
 set-webroot(){
-    if [ $# == 1 ]
-    then
+    local sed_command
+    if [[ $# == 1 ]]; then
       # assume the openemr parameter was given, so set openemr webroot
       echo "changing webroot to openemr"
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs@g' /etc/apache2/conf.d/openemr.conf"
+      sed_command="sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs@g' /etc/apache2/conf.d/openemr.conf"
     else
       # set to blank, so set blank webroot
       echo "changing webroot to blank"
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs/openemr@g' /etc/apache2/conf.d/openemr.conf"
+      sed_command="sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs/openemr@g' /etc/apache2/conf.d/openemr.conf"
     fi
+    # Use the function for arbitrary commands
+    run_shell_command_in_docker "${CONTAINER_ID}" "${sed_command}"
     # restart the docker
     echo "restarting openemr docker so the apache configuration change will take effect"
-    docker restart "$CONTAINER_ID"
+    docker restart "${CONTAINER_ID}"
 }
 
 docker-pull-image(){
+    local docker_images
     docker_images=$(docker ps --format "table {{.Image}}")
-    for IMAGE in $docker_images
-    do
-    if [ $IMAGE != "IMAGE" ] 
-    then
-      read -e -p "Do you wish to pull $IMAGE ? (y) " RESP
-      if [ "$RESP" = "y" ]; then 
-        docker pull "$IMAGE";
-      else 
-        echo "Skipping $IMAGE";
+    local IMAGE RESP
+    for IMAGE in ${docker_images}; do
+      if [[ "${IMAGE}" != "IMAGE" ]]; then
+        # Use -r with read
+        read -r -e -p "Do you wish to pull ${IMAGE} ? (y) " RESP
+        if [[ "${RESP}" == "y" ]]; then
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: ```suggestion
        if [[ "${RESP,,}" = y ]]; then
```

the ,, makes it case insensitive, and the double `==` provides no advantage over, `=`. (IMO we should avoid bashisms unless they provide some advantage. Unfortunately once shellcheck knows this is bash, it doesn't flag `==`.)
created_at: 2025-04-24T16:51:15Z
author_association: MEMBER
diff_hunk: @@ -294,15 +325,16 @@ FINAL_EXIT_CODE=0
 
 # Confirm the docker install or not.
 DOCKER_CODE=16
-which docker &>/dev/null
-[ $? -ne 0 ] && echo "Please check docker install or not." && exit $DOCKER_CODE
+if ! command -v docker &>/dev/null; then
+  echo "Please check docker install or not."
+  exit "${DOCKER_CODE}"
+fi
 
 # Script usage.
-if [ $# -eq 0 ] || [ "$FIRST_ARG" == '--help' ] || [ "$FIRST_ARG" == '-h' ]
-then
+if [[ $# -eq 0 ]] || [[ "${FIRST_ARG}" == '--help' ]] || [[ "${FIRST_ARG}" == '-h' ]]; then
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: ```suggestion
if [[ $# -eq 0 || "${FIRST_ARG}" = '--help' || "${FIRST_ARG}" = '-h' ]]; then
```
created_at: 2025-04-24T16:52:24Z
author_association: MEMBER
diff_hunk: @@ -321,125 +353,151 @@ then
   echo "  dpi, docker-pull-image             Prompt to pull docker image"
   echo 'php-management:'
   echo "  bt, build-themes                   Make changes to any files on your local file system"
-	echo "  pl, php-log                        To check PHP error logs"
-	echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
-	echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
-	echo "  ltr, lint-themes-report            To create a report of theme styling issues"
-	echo "  ltf, lint-themes-fix               To fix theme styling issues"
+  echo "  pl, php-log                        To check PHP error logs"
+  echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
+  echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
+  echo "  ltr, lint-themes-report            To create a report of theme styling issues"
+  echo "  ltf, lint-themes-fix               To fix theme styling issues"
   echo "  ljr, lint-javascript-report        To create a report of javascript styling issues"
   echo "  ljf, lint-javascript-fix           To fix javascript styling issues"
-	echo "  pp, php-parserror                  To check PHP parsing errors"
-	echo "  xl, xdebug-log                     To check xdebug log"
-	echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
+  echo "  pp, php-parserror                  To check PHP parsing errors"
+  echo "  xl, xdebug-log                     To check xdebug log"
+  echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
   echo 'test-management:'
-	echo "  ut, unit-test                      To run php unit testing"
-	echo "  jut, javascript-unit-test          To run javascript unit testing"
-	echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
-	echo "  at, api-test                       To run api testing"
-	echo "  et, e2e-test                       To run e2e testing"
-	echo "  st, services-test                  To run services testing"
-	echo "  ft, fixtures-test                  To run fixtures testing"
-	echo "  vt, validators-test                To run validators testing"
-	echo "  ct, controllers-test               To run controllers testing"
-	echo "  ctt, common-test                   To run common testing"
+  echo "  ut, unit-test                      To run php unit testing"
+  echo "  jut, javascript-unit-test          To run javascript unit testing"
+  echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
+  echo "  at, api-test                       To run api testing"
+  echo "  et, e2e-test                       To run e2e testing"
+  echo "  st, services-test                  To run services testing"
+  echo "  ft, fixtures-test                  To run fixtures testing"
+  echo "  vt, validators-test                To run validators testing"
+  echo "  ct, controllers-test               To run controllers testing"
+  echo "  ctt, common-test                   To run common testing"
   echo 'sweep-management:'
-	echo "  cs, clean-sweep                    To run the entire dev tool suite"
-	echo "  cst, clean-sweep-tests             To run only all the automated tests"
-  echo 'reset-mamagement:'
-	echo "  dr, dev-reset                      To reset OpenEMR only"
-	echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
-	echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
-	echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
+  echo "  cs, clean-sweep                    To run the entire dev tool suite"
+  echo "  cst, clean-sweep-tests             To run only all the automated tests"
+  echo 'reset-management:'
+  echo "  dr, dev-reset                      To reset OpenEMR only"
+  echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
+  echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
+  echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
   echo 'backup-management:'
-	echo "  bs, backup-snapshot                Create a backup snapshot"
-	echo "  rs, restore-snapshot               Restore from a snapshot"
-	echo "  ls, list-snapshots                 To list the snapshots"
-	echo "  lc, list-capsules                  List the capsules"
-	echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
-	echo "  pc, put-capsule                    Copy the capsule into the docker"
+  echo "  bs, backup-snapshot                Create a backup snapshot"
+  echo "  rs, restore-snapshot               Restore from a snapshot"
+  echo "  ls, list-snapshots                 To list the snapshots"
+  echo "  lc, list-capsules                  List the capsules"
+  echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
+  echo "  pc, put-capsule                    Copy the capsule into the docker"
   echo 'ssl-management:'
-	echo "  fh, force-https                    Force https"
-	echo "  ufh, un-force-https                Removing forcing of https"
-	echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
-	echo "  scc, setup-client-cert             Turn on client based cert with designated package"
-	echo "  lcc, list-client-certs             To list the certificate packages"
-	echo "  pcc, put-client-cert               To copy certificate package into the docker"
-	echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
+  echo "  fh, force-https                    Force https"
+  echo "  ufh, un-force-https                Removing forcing of https"
+  echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
+  echo "  scc, setup-client-cert             Turn on client based cert with designated package"
+  echo "  lcc, list-client-certs             To list the certificate packages"
+  echo "  pcc, put-client-cert               To copy certificate package into the docker"
+  echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
   echo "  sso, sql-ssl-off                   Remove testing sql ssl CA cert"
   echo "  ssc, sql-ssl-client                Use testing sql ssl client certs"
   echo "  ssco, sql-ssl-client-off           Remove testing sql ssl client certs"
-	echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
+  echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
   echo "  cso, couchdb-ssl-off               Remove testing couchdb ssl CA cert"
   echo "  csc, couchdb-ssl-client            Use testing couchdb ssl client certs"
   echo "  csco, couchdb-ssl-client-off       Remove testing couchdb ssl client certs"
-	echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
+  echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
   echo "  lso, ldap-ssl-off                  Remove testing ldap ssl CA cert"
   echo "  lsc, ldap-ssl-client               Use testing ldap ssl client certs"
   echo "  lsco, ldap-ssl-client-off          Remove testing ldap ssl client certs"
   echo 'multisite-management:'
   echo "  lm, list-multisites                List multisites"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
-	echo "  em, enable-multisite               Turn on support for multisite in setup.php"
-	echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  em, enable-multisite               Turn on support for multisite in setup.php"
+  echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
   echo 'api-management:'
   echo "  bad, build-api-docs                Build and place api documentation/configuration for swagger"
   echo "  roc, register-oauth2-client        Register oauth2 client (returns client id/secret)"
   echo "  rocd, register-oauth2-client-demo  Register oauth2 client (returns client id/secret) on online demo"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
   echo 'computational-health-informatics:'
-	echo "  irp, import-random-patients        Create and import random patients <number patients>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  irp, import-random-patients        Create and import random patients <number patients>"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
   echo 'webroot-management:'
-	echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
-	echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
+  echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
+  echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
   echo 'others:'
-	echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
-	echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
-	echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
-	echo "  ec, encoding-collation             Change the database character set and collation"
-
-	exit $USAGE_EXIT_CODE
-elif [ "$FIRST_ARG" == '--version' ] || [ "$FIRST_ARG" == '-v' ]
-then
-	echo "openemr-cmd $VERSION"
-	exit $VERSION_EXIT_CODE
+  echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
+  echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
+  echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
+  echo "  ec, encoding-collation             Change the database character set and collation"
+
+  exit "${USAGE_EXIT_CODE}"
+
+elif [[ "${FIRST_ARG}" == '--version' ]] || [[ "${FIRST_ARG}" == '-v' ]]; then
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: ```suggestion
elif [[ "${FIRST_ARG}" = '--version' || "${FIRST_ARG}" = '-v' ]]; then
```
created_at: 2025-04-24T16:52:48Z
author_association: MEMBER
diff_hunk: @@ -321,125 +353,151 @@ then
   echo "  dpi, docker-pull-image             Prompt to pull docker image"
   echo 'php-management:'
   echo "  bt, build-themes                   Make changes to any files on your local file system"
-	echo "  pl, php-log                        To check PHP error logs"
-	echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
-	echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
-	echo "  ltr, lint-themes-report            To create a report of theme styling issues"
-	echo "  ltf, lint-themes-fix               To fix theme styling issues"
+  echo "  pl, php-log                        To check PHP error logs"
+  echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
+  echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
+  echo "  ltr, lint-themes-report            To create a report of theme styling issues"
+  echo "  ltf, lint-themes-fix               To fix theme styling issues"
   echo "  ljr, lint-javascript-report        To create a report of javascript styling issues"
   echo "  ljf, lint-javascript-fix           To fix javascript styling issues"
-	echo "  pp, php-parserror                  To check PHP parsing errors"
-	echo "  xl, xdebug-log                     To check xdebug log"
-	echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
+  echo "  pp, php-parserror                  To check PHP parsing errors"
+  echo "  xl, xdebug-log                     To check xdebug log"
+  echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
   echo 'test-management:'
-	echo "  ut, unit-test                      To run php unit testing"
-	echo "  jut, javascript-unit-test          To run javascript unit testing"
-	echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
-	echo "  at, api-test                       To run api testing"
-	echo "  et, e2e-test                       To run e2e testing"
-	echo "  st, services-test                  To run services testing"
-	echo "  ft, fixtures-test                  To run fixtures testing"
-	echo "  vt, validators-test                To run validators testing"
-	echo "  ct, controllers-test               To run controllers testing"
-	echo "  ctt, common-test                   To run common testing"
+  echo "  ut, unit-test                      To run php unit testing"
+  echo "  jut, javascript-unit-test          To run javascript unit testing"
+  echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
+  echo "  at, api-test                       To run api testing"
+  echo "  et, e2e-test                       To run e2e testing"
+  echo "  st, services-test                  To run services testing"
+  echo "  ft, fixtures-test                  To run fixtures testing"
+  echo "  vt, validators-test                To run validators testing"
+  echo "  ct, controllers-test               To run controllers testing"
+  echo "  ctt, common-test                   To run common testing"
   echo 'sweep-management:'
-	echo "  cs, clean-sweep                    To run the entire dev tool suite"
-	echo "  cst, clean-sweep-tests             To run only all the automated tests"
-  echo 'reset-mamagement:'
-	echo "  dr, dev-reset                      To reset OpenEMR only"
-	echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
-	echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
-	echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
+  echo "  cs, clean-sweep                    To run the entire dev tool suite"
+  echo "  cst, clean-sweep-tests             To run only all the automated tests"
+  echo 'reset-management:'
+  echo "  dr, dev-reset                      To reset OpenEMR only"
+  echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
+  echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
+  echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
   echo 'backup-management:'
-	echo "  bs, backup-snapshot                Create a backup snapshot"
-	echo "  rs, restore-snapshot               Restore from a snapshot"
-	echo "  ls, list-snapshots                 To list the snapshots"
-	echo "  lc, list-capsules                  List the capsules"
-	echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
-	echo "  pc, put-capsule                    Copy the capsule into the docker"
+  echo "  bs, backup-snapshot                Create a backup snapshot"
+  echo "  rs, restore-snapshot               Restore from a snapshot"
+  echo "  ls, list-snapshots                 To list the snapshots"
+  echo "  lc, list-capsules                  List the capsules"
+  echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
+  echo "  pc, put-capsule                    Copy the capsule into the docker"
   echo 'ssl-management:'
-	echo "  fh, force-https                    Force https"
-	echo "  ufh, un-force-https                Removing forcing of https"
-	echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
-	echo "  scc, setup-client-cert             Turn on client based cert with designated package"
-	echo "  lcc, list-client-certs             To list the certificate packages"
-	echo "  pcc, put-client-cert               To copy certificate package into the docker"
-	echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
+  echo "  fh, force-https                    Force https"
+  echo "  ufh, un-force-https                Removing forcing of https"
+  echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
+  echo "  scc, setup-client-cert             Turn on client based cert with designated package"
+  echo "  lcc, list-client-certs             To list the certificate packages"
+  echo "  pcc, put-client-cert               To copy certificate package into the docker"
+  echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
   echo "  sso, sql-ssl-off                   Remove testing sql ssl CA cert"
   echo "  ssc, sql-ssl-client                Use testing sql ssl client certs"
   echo "  ssco, sql-ssl-client-off           Remove testing sql ssl client certs"
-	echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
+  echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
   echo "  cso, couchdb-ssl-off               Remove testing couchdb ssl CA cert"
   echo "  csc, couchdb-ssl-client            Use testing couchdb ssl client certs"
   echo "  csco, couchdb-ssl-client-off       Remove testing couchdb ssl client certs"
-	echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
+  echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
   echo "  lso, ldap-ssl-off                  Remove testing ldap ssl CA cert"
   echo "  lsc, ldap-ssl-client               Use testing ldap ssl client certs"
   echo "  lsco, ldap-ssl-client-off          Remove testing ldap ssl client certs"
   echo 'multisite-management:'
   echo "  lm, list-multisites                List multisites"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
-	echo "  em, enable-multisite               Turn on support for multisite in setup.php"
-	echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  em, enable-multisite               Turn on support for multisite in setup.php"
+  echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
   echo 'api-management:'
   echo "  bad, build-api-docs                Build and place api documentation/configuration for swagger"
   echo "  roc, register-oauth2-client        Register oauth2 client (returns client id/secret)"
   echo "  rocd, register-oauth2-client-demo  Register oauth2 client (returns client id/secret) on online demo"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
   echo 'computational-health-informatics:'
-	echo "  irp, import-random-patients        Create and import random patients <number patients>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  irp, import-random-patients        Create and import random patients <number patients>"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
   echo 'webroot-management:'
-	echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
-	echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
+  echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
+  echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
   echo 'others:'
-	echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
-	echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
-	echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
-	echo "  ec, encoding-collation             Change the database character set and collation"
-
-	exit $USAGE_EXIT_CODE
-elif [ "$FIRST_ARG" == '--version' ] || [ "$FIRST_ARG" == '-v' ]
-then
-	echo "openemr-cmd $VERSION"
-	exit $VERSION_EXIT_CODE
+  echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
+  echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
+  echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
+  echo "  ec, encoding-collation             Change the database character set and collation"
+
+  exit "${USAGE_EXIT_CODE}"
+
+elif [[ "${FIRST_ARG}" == '--version' ]] || [[ "${FIRST_ARG}" == '-v' ]]; then
+	echo "openemr-cmd ${VERSION}"
+	exit "${VERSION_EXIT_CODE}"
 fi
 
 # Specify the docker id/name to execute the commands.
-#  default to insane dev docker, if exists
-CONTAINER_ID=$(docker ps | grep $INSANE_DEV_DOCKER | cut -f 1 -d " ")
-if [ -z $CONTAINER_ID ]
-then
-  # else, default to easy dev docker, if exists
-  CONTAINER_ID=$(docker ps | grep $EASY_DEV_DOCKER | cut -f 1 -d " ")
+# Default to insane dev docker, if exists, otherwise easy dev docker.
+# Try to find the insane dev docker ID directly
+if insane_id=$(docker ps --filter "name=${INSANE_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${insane_id}" ]]; then
+  CONTAINER_ID="${insane_id}"
+# Try to find the easy dev docker ID directly
+elif easy_id=$(docker ps --filter "name=${EASY_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${easy_id}" ]]; then
+  CONTAINER_ID="${easy_id}"
+else
+  # Neither container found running, set CONTAINER_ID to empty.
+  # The script's later logic handles the -d flag or errors if no container is specified.
+  CONTAINER_ID=""
 fi
+
 # override the default container setting if supplied via the -d parameter
 #  (also removing no longer needed parameters via shift)
 CHANGE_CONTAINER_CODE=25
-if [ "$FIRST_ARG" == '-d' ] && [ $# -ge 3 ]
-then
-	CONTAINER_ID=$2
-	FIRST_ARG=$3
+if [[ "${FIRST_ARG}" == '-d' ]] && [[ $# -ge 3 ]]; then
+	CONTAINER_ID="$2"
+	FIRST_ARG="$3"
 	shift 3
-elif [ "$FIRST_ARG" == '-d' ] && [ $# -lt 3 ]
-then
+elif [[ "${FIRST_ARG}" == '-d' ]] && [[ $# -lt 3 ]]; then
 	echo 'Please provide a docker id/name when using -d parameter.'
 	echo 'e.g. openemr-cmd -d docker_openemr-7-3-redis-312_1 dl'
-	exit $CHANGE_CONTAINER_CODE
+	exit "${CHANGE_CONTAINER_CODE}"
 else
   shift
 fi
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: ```suggestion
if [[ "${FIRST_ARG}" = '-d' ]]; then
  if (( $# < 3 )); then
    echo 'Please provide a docker id/name when using -d parameter.'
    echo 'e.g. openemr-cmd -d docker_openemr-7-3-redis-312_1 dl'
    exit "${CHANGE_CONTAINER_CODE}"
  fi
  CONTAINER_ID="$2"
  FIRST_ARG="$3"
  shift 3
else
  shift
fi
```
created_at: 2025-04-24T16:56:59Z
author_association: MEMBER
diff_hunk: @@ -321,125 +353,151 @@ then
   echo "  dpi, docker-pull-image             Prompt to pull docker image"
   echo 'php-management:'
   echo "  bt, build-themes                   Make changes to any files on your local file system"
-	echo "  pl, php-log                        To check PHP error logs"
-	echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
-	echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
-	echo "  ltr, lint-themes-report            To create a report of theme styling issues"
-	echo "  ltf, lint-themes-fix               To fix theme styling issues"
+  echo "  pl, php-log                        To check PHP error logs"
+  echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
+  echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
+  echo "  ltr, lint-themes-report            To create a report of theme styling issues"
+  echo "  ltf, lint-themes-fix               To fix theme styling issues"
   echo "  ljr, lint-javascript-report        To create a report of javascript styling issues"
   echo "  ljf, lint-javascript-fix           To fix javascript styling issues"
-	echo "  pp, php-parserror                  To check PHP parsing errors"
-	echo "  xl, xdebug-log                     To check xdebug log"
-	echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
+  echo "  pp, php-parserror                  To check PHP parsing errors"
+  echo "  xl, xdebug-log                     To check xdebug log"
+  echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
   echo 'test-management:'
-	echo "  ut, unit-test                      To run php unit testing"
-	echo "  jut, javascript-unit-test          To run javascript unit testing"
-	echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
-	echo "  at, api-test                       To run api testing"
-	echo "  et, e2e-test                       To run e2e testing"
-	echo "  st, services-test                  To run services testing"
-	echo "  ft, fixtures-test                  To run fixtures testing"
-	echo "  vt, validators-test                To run validators testing"
-	echo "  ct, controllers-test               To run controllers testing"
-	echo "  ctt, common-test                   To run common testing"
+  echo "  ut, unit-test                      To run php unit testing"
+  echo "  jut, javascript-unit-test          To run javascript unit testing"
+  echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
+  echo "  at, api-test                       To run api testing"
+  echo "  et, e2e-test                       To run e2e testing"
+  echo "  st, services-test                  To run services testing"
+  echo "  ft, fixtures-test                  To run fixtures testing"
+  echo "  vt, validators-test                To run validators testing"
+  echo "  ct, controllers-test               To run controllers testing"
+  echo "  ctt, common-test                   To run common testing"
   echo 'sweep-management:'
-	echo "  cs, clean-sweep                    To run the entire dev tool suite"
-	echo "  cst, clean-sweep-tests             To run only all the automated tests"
-  echo 'reset-mamagement:'
-	echo "  dr, dev-reset                      To reset OpenEMR only"
-	echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
-	echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
-	echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
+  echo "  cs, clean-sweep                    To run the entire dev tool suite"
+  echo "  cst, clean-sweep-tests             To run only all the automated tests"
+  echo 'reset-management:'
+  echo "  dr, dev-reset                      To reset OpenEMR only"
+  echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
+  echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
+  echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
   echo 'backup-management:'
-	echo "  bs, backup-snapshot                Create a backup snapshot"
-	echo "  rs, restore-snapshot               Restore from a snapshot"
-	echo "  ls, list-snapshots                 To list the snapshots"
-	echo "  lc, list-capsules                  List the capsules"
-	echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
-	echo "  pc, put-capsule                    Copy the capsule into the docker"
+  echo "  bs, backup-snapshot                Create a backup snapshot"
+  echo "  rs, restore-snapshot               Restore from a snapshot"
+  echo "  ls, list-snapshots                 To list the snapshots"
+  echo "  lc, list-capsules                  List the capsules"
+  echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
+  echo "  pc, put-capsule                    Copy the capsule into the docker"
   echo 'ssl-management:'
-	echo "  fh, force-https                    Force https"
-	echo "  ufh, un-force-https                Removing forcing of https"
-	echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
-	echo "  scc, setup-client-cert             Turn on client based cert with designated package"
-	echo "  lcc, list-client-certs             To list the certificate packages"
-	echo "  pcc, put-client-cert               To copy certificate package into the docker"
-	echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
+  echo "  fh, force-https                    Force https"
+  echo "  ufh, un-force-https                Removing forcing of https"
+  echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
+  echo "  scc, setup-client-cert             Turn on client based cert with designated package"
+  echo "  lcc, list-client-certs             To list the certificate packages"
+  echo "  pcc, put-client-cert               To copy certificate package into the docker"
+  echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
   echo "  sso, sql-ssl-off                   Remove testing sql ssl CA cert"
   echo "  ssc, sql-ssl-client                Use testing sql ssl client certs"
   echo "  ssco, sql-ssl-client-off           Remove testing sql ssl client certs"
-	echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
+  echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
   echo "  cso, couchdb-ssl-off               Remove testing couchdb ssl CA cert"
   echo "  csc, couchdb-ssl-client            Use testing couchdb ssl client certs"
   echo "  csco, couchdb-ssl-client-off       Remove testing couchdb ssl client certs"
-	echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
+  echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
   echo "  lso, ldap-ssl-off                  Remove testing ldap ssl CA cert"
   echo "  lsc, ldap-ssl-client               Use testing ldap ssl client certs"
   echo "  lsco, ldap-ssl-client-off          Remove testing ldap ssl client certs"
   echo 'multisite-management:'
   echo "  lm, list-multisites                List multisites"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
-	echo "  em, enable-multisite               Turn on support for multisite in setup.php"
-	echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  em, enable-multisite               Turn on support for multisite in setup.php"
+  echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
   echo 'api-management:'
   echo "  bad, build-api-docs                Build and place api documentation/configuration for swagger"
   echo "  roc, register-oauth2-client        Register oauth2 client (returns client id/secret)"
   echo "  rocd, register-oauth2-client-demo  Register oauth2 client (returns client id/secret) on online demo"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
   echo 'computational-health-informatics:'
-	echo "  irp, import-random-patients        Create and import random patients <number patients>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  irp, import-random-patients        Create and import random patients <number patients>"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
   echo 'webroot-management:'
-	echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
-	echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
+  echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
+  echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
   echo 'others:'
-	echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
-	echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
-	echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
-	echo "  ec, encoding-collation             Change the database character set and collation"
-
-	exit $USAGE_EXIT_CODE
-elif [ "$FIRST_ARG" == '--version' ] || [ "$FIRST_ARG" == '-v' ]
-then
-	echo "openemr-cmd $VERSION"
-	exit $VERSION_EXIT_CODE
+  echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
+  echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
+  echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
+  echo "  ec, encoding-collation             Change the database character set and collation"
+
+  exit "${USAGE_EXIT_CODE}"
+
+elif [[ "${FIRST_ARG}" == '--version' ]] || [[ "${FIRST_ARG}" == '-v' ]]; then
+	echo "openemr-cmd ${VERSION}"
+	exit "${VERSION_EXIT_CODE}"
 fi
 
 # Specify the docker id/name to execute the commands.
-#  default to insane dev docker, if exists
-CONTAINER_ID=$(docker ps | grep $INSANE_DEV_DOCKER | cut -f 1 -d " ")
-if [ -z $CONTAINER_ID ]
-then
-  # else, default to easy dev docker, if exists
-  CONTAINER_ID=$(docker ps | grep $EASY_DEV_DOCKER | cut -f 1 -d " ")
+# Default to insane dev docker, if exists, otherwise easy dev docker.
+# Try to find the insane dev docker ID directly
+if insane_id=$(docker ps --filter "name=${INSANE_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${insane_id}" ]]; then
+  CONTAINER_ID="${insane_id}"
+# Try to find the easy dev docker ID directly
+elif easy_id=$(docker ps --filter "name=${EASY_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${easy_id}" ]]; then
+  CONTAINER_ID="${easy_id}"
+else
+  # Neither container found running, set CONTAINER_ID to empty.
+  # The script's later logic handles the -d flag or errors if no container is specified.
+  CONTAINER_ID=""
 fi
+
 # override the default container setting if supplied via the -d parameter
 #  (also removing no longer needed parameters via shift)
 CHANGE_CONTAINER_CODE=25
-if [ "$FIRST_ARG" == '-d' ] && [ $# -ge 3 ]
-then
-	CONTAINER_ID=$2
-	FIRST_ARG=$3
+if [[ "${FIRST_ARG}" == '-d' ]] && [[ $# -ge 3 ]]; then
+	CONTAINER_ID="$2"
+	FIRST_ARG="$3"
 	shift 3
-elif [ "$FIRST_ARG" == '-d' ] && [ $# -lt 3 ]
-then
+elif [[ "${FIRST_ARG}" == '-d' ]] && [[ $# -lt 3 ]]; then
 	echo 'Please provide a docker id/name when using -d parameter.'
 	echo 'e.g. openemr-cmd -d docker_openemr-7-3-redis-312_1 dl'
-	exit $CHANGE_CONTAINER_CODE
+	exit "${CHANGE_CONTAINER_CODE}"
 else
   shift
 fi
 
 #collect the couchdb docker name
-COUCHDB_CONTAINER=$(docker ps | grep $COUCHDB_DOCKER | cut -f 1 -d " ")
+# Use docker ps --filter and --format for efficiency and robustness
+couchdb_id=$(docker ps --filter "name=${COUCHDB_DOCKER}" --format "{{.ID}}" | head -n 1)
+COUCHDB_CONTAINER="${couchdb_id:-}" # Set to empty if not found
 
 # Collect the mariadb container id
-MARIADB_CONTAINER_ID=$(docker ps | grep $MARIADB_DOCKER | cut -f 1 -d " ")
+# Use docker ps --filter and --format for efficiency and robustness
+mariadb_id=$(docker ps --filter "name=${MARIADB_DOCKER}" --format "{{.ID}}" | head -n 1)
+MARIADB_CONTAINER_ID="${mariadb_id:-}" # Set to empty if not found
+
+# Check if a target container ID was determined or provided before proceeding with commands that need it
+# (Allow proceeding if the command doesn't require a container, like up, down, start, stop, --help, --version)
+case "${FIRST_ARG}" in
+  up|down|start|stop|--help|-h|--version|-v)
+    # These commands don't necessarily need a running container ID determined here
+    ;;
+  *)
+    # All other commands likely need a CONTAINER_ID
+    # Check if CONTAINER_ID is empty AND -d wasn't the *original* first arg
+    if [[ -z "${CONTAINER_ID}" ]] && [[ "${FIRST_ARG}" != '-d' ]]; then
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: ```suggestion
    if [[ -z "${CONTAINER_ID}" && "${FIRST_ARG}" != '-d' ]]; then
```
created_at: 2025-04-24T16:57:54Z
author_association: MEMBER
diff_hunk: @@ -24,267 +30,292 @@ get_container_names() {
 # Set the container names
 get_container_names
 
+# Function to run the devtools script inside the specified container
+# Usage: run_devtools_in_docker <container_id> <devtools_command> [args...]
+run_devtools_in_docker() {
+  local container_id="$1"
+  shift # Remove container_id from arguments
+  # DEV_TOOLS is '/root/devtools'
+  # "$@" passes the remaining arguments (devtools command and its args) correctly quoted
+  docker exec -i "${container_id}" "${DEV_TOOLS}" "$@"
+}
+
+# Function to run an arbitrary shell command string inside the specified container
+# Usage: run_shell_command_in_docker <container_id> <command_string>
+run_shell_command_in_docker() {
+  local container_id="$1"
+  local command_string="$2"
+  docker exec -i "${container_id}" sh -c "${command_string}"
+}
+
 # Set some constants
-DOCKER_EXEC_CMD='docker exec -i'                                 # docker exec command
-SHELL_TYPE='sh -c'                                               # specify shell type
-FIRST_ARG=$1											                               # define the first parameter
-DEV_TOOLS=/root/devtools
+FIRST_ARG="${1:-}" # define the first parameter, default to empty if not set
+DEV_TOOLS='/root/devtools'
 
 check_docker_compose_install_or_not(){
-	DOCKER_COMPOSE_CODE=22
-	which docker-compose &>/dev/null
-	[ $? -ne 0 ] && echo "Please check docker-compose install or not." && exit $DOCKER_COMPOSE_CODE
+	local DOCKER_COMPOSE_CODE=22
+	if ! command -v docker-compose &>/dev/null; then
+		echo "Please check docker-compose install or not."
+    exit "${DOCKER_COMPOSE_CODE}"
+	fi
 }
 
 quick_open_a_docker_shell(){
-  docker exec -w /var/www/localhost/htdocs/openemr -it $CONTAINER_ID sh
+  docker exec -w /var/www/localhost/htdocs/openemr -it "${CONTAINER_ID}" sh
 }
 
 quick_open_a_maria_docker_shell(){
-  docker exec -it $MARIADB_CONTAINER_ID /bin/bash
+  docker exec -it "${MARIADB_CONTAINER_ID}" /bin/bash
 }
 
 execute_command_flexible(){
-	if [ $# -lt 1 ]
-	then
+	if [[ $# -lt 1 ]]; then
 		echo "Please provide the command."
-		echo "e.g. `basename $0` [exec|e] \"tail -f /var/log/apache2/error.log\""
-		echo "e.g. `basename $0` -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$@"
+		# Use the function for arbitrary commands
+		run_shell_command_in_docker "${CONTAINER_ID}" "$@"
 	fi
 }
 
 check_docker_log() {
-  docker logs $CONTAINER_ID
+  docker logs "${CONTAINER_ID}"
 }
 
 check_docker_names() {
-	CHECK_NAME=$1     # specify the checking name
-	if [ $# -eq 1 ]
-	then
+	if [[ $# -eq 1 ]]; then
 		# ARGS: couchdb php fhir mariadb mysql nginx openemr openldap orthanc redis.
+        # specify the name to check
+        local CHECK_NAME="$1"
 		echo '===Check the single Docker Name==='
 		echo '  STATUS        NAME'
-		docker ps -a --format "{{.Status}}\t{{.Names}}"| grep $CHECK_NAME
+        # Capture output, check if empty
+        local matching_container
+        matching_container=$(docker ps -a --format "{{.Status}}\t{{.Names}}"| grep "${CHECK_NAME}" || true) # Keep || true here, and below, to prevent exit during capture
+        if [[ -z "${matching_container}" ]]; then
+            echo "No containers found matching '${CHECK_NAME}'"
+        else
+            echo "${matching_container}"
+        fi
 
 	else
 		# Show all the docker names.
 		echo '***************************************************************'
 		echo 'Show all the docker names by default.'
 		echo 'Please provide the keyword if you want to check the single one.'
-		echo "e.g `basename $0` [docker-names|dn] php"
+		echo "e.g $(basename "$0") [docker-names|dn] php"
 		echo '***************************************************************'
 		echo '=======Running Docker Names======='
-		docker ps | awk '{print $NF}'|grep -v NAMES|sort -n
+		
+        # Capture output, check if empty
+        local running_containers
+        running_containers=$(docker ps --format "{{.Status}}\t{{.Names}}" | { grep -v NAMES || true; } | sort -n)
+        if [[ -z "${running_containers}" ]]; then
+            echo "No running containers found."
+        else
+		    echo '  STATUS        NAME'
+            echo "${running_containers}"
+        fi
 		echo '====Other Docker Status Names====='
-		docker ps -a --format "table{{.Status}}\t{{.Names}}"| grep -v Up
+        # Capture output, check if empty
+        local other_containers
+        other_containers=$(docker ps -a --format "{{.Status}}\t{{.Names}}" | grep -v Up || true)
+        if [[ -z "${other_containers}" ]]; then
+            echo "No containers found with other statuses."
+        else
+		    echo '  STATUS        NAME'
+            echo "${other_containers}"
+        fi
 	fi
 }
 
 restart_couchdb_docker(){
-  if [ -z "$COUCHDB_CONTAINER" ]
-  then
+  if [[ -z "${COUCHDB_CONTAINER}" ]]; then
     echo "Unable to find the couchdb docker, so could not restart it"
   else
     echo "Restarting couchdb docker"
-    docker restart "$COUCHDB_CONTAINER"
+    docker restart "${COUCHDB_CONTAINER}"
   fi
 }
 
 creat_a_backup_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=20
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=20
+    if [[ $# != 1 ]]; then
 		echo 'Please provide a snapshot name.'
 		echo 'e.g. openemr-cmd [backup-snapshot|bs] example'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS backup $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" backup "${BACKUP_FILE}"
 	fi
 }
 
 restore_from_a_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=21
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=21
+    if [[ $# != 1 ]]; then
         echo 'Please provide a restore snapshot name.'
         echo 'e.g. openemr-cmd [restore-snapshot|rs] example'
-        exit $BACKUP_FILE_CODE
+        exit "${BACKUP_FILE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS restore $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" restore "${BACKUP_FILE}"
 	fi
 }
 
 copy_capsule_from_docker_to_host(){
-	BACKUP_FILE=$1
-	BACKUP_HOST_DIR=$2 #optional parameter
-	BACKUP_FILE_CODE=19
-	if [ $# != 1 ] && [ $# != 2 ]
-	then
+	local BACKUP_FILE="$1"
+	local BACKUP_HOST_DIR="${2:-}" #optional parameter, default to empty
+	local BACKUP_FILE_CODE=19
+	if [[ $# != 1 ]] && [[ $# != 2 ]]; then
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: ```suggestion
	if (( $# != 1 && $# != 2 )); then
```

(Although if I had my druthers we'd flip negative if expressions and this'd start with `(( $# == 1 || $# == 2 ))`.)
created_at: 2025-04-24T17:02:40Z
author_association: MEMBER
diff_hunk: @@ -69,5 +76,9 @@ case "$FIRST_ARG" in
 		openemr-cmd -h
 		;;
 		*)
-		openemr-cmd -h|grep -i $FIRST_ARG
+		# Quoted variable
+		openemr-cmd -h | grep -i "${FIRST_ARG}"
+		;;
 esac
+
+exit 0 # Explicit success exit at end of script
path: utilities/openemr-cmd/openemr-cmd-h
user: login: kojiromike
body: Was this a shellcheck suggestion? It seems unnecessary, as the script will always exit early if there's an error (due to `set -e` at the top).
created_at: 2025-04-24T17:06:53Z
author_association: MEMBER
diff_hunk: @@ -1,13 +1,18 @@
 #!/bin/bash
-FIRST_ARG=$1
+
+set -euo pipefail # Exit on error, unset var, pipe failure
+
+FIRST_ARG="${1:-}" # Use parameter expansion default
 
 filter_help_output(){
-	FILTER_ARG=$1
-	LINE_COUNT=$2
-	openemr-cmd -h|grep $FILTER_ARG -A $LINE_COUNT
+	local FILTER_ARG="$1"
+	local LINE_COUNT="$2"
+	# Quoted variables
+	openemr-cmd -h | grep "${FILTER_ARG}" -A "${LINE_COUNT}"
 }
 
-if [ $# -eq 0 ]
+# Use [[ ]] for test
+if [[ $# -eq 0 ]]
path: utilities/openemr-cmd/openemr-cmd-h
user: login: kojiromike
body: ```suggestion
# Use (( )) for numeric comparisons
if (( $# == 0 ))
```
created_at: 2025-04-24T17:07:44Z
author_association: MEMBER
diff_hunk: @@ -496,190 +554,191 @@ case "$FIRST_ARG" in
 	pcc|put-client-cert)
 		put-client-cert "$@"
 		;;
-  irp|import-random-patients)
-    import-random-patients "$@"
-		;;
-  rocd|register-oauth2-client-demo)
-    register-oauth2-client-demo "$@"
-		;;
-  roc|register-oauth2-client)
-    register-oauth2-client "$@"
-		;;
-  swtm|set-swagger-to-multisite)
-    set-swagger-to-multisite "$@"
-		;;
-  cwb|change-webroot-blank)
-    set-webroot
-		;;
-  cwo|change-webroot-openemr)
-    set-webroot openemr
-		;;
-  ms|maria-shell)
-    quick_open_a_maria_docker_shell
-		;;
+    irp|import-random-patients)
+        import-random-patients "$@"
+        ;;
+    rocd|register-oauth2-client-demo)
+        register-oauth2-client-demo "$@"
+        ;;
+    roc|register-oauth2-client)
+        register-oauth2-client "$@"
+        ;;
+    swtm|set-swagger-to-multisite)
+        set-swagger-to-multisite "$@"
+        ;;
+    cwb|change-webroot-blank)
+        set-webroot
+        ;;
+    cwo|change-webroot-openemr)
+        set-webroot openemr
+        ;;
+    ms|maria-shell)
+        quick_open_a_maria_docker_shell
+        ;;
 	bt)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS build-themes"
+		run_devtools_in_docker "${CONTAINER_ID}" build-themes
 		;;
 	pl)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS php-log"
+		run_devtools_in_docker "${CONTAINER_ID}" php-log
 		;;
 	pr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS psr12-report"
+		run_devtools_in_docker "${CONTAINER_ID}" psr12-report
 		;;
 	pf)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS psr12-fix"
+		run_devtools_in_docker "${CONTAINER_ID}" psr12-fix
 		;;
 	ltr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-themes-report"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-themes-report
 		;;
 	ltf)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-themes-fix"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-themes-fix
 		;;
 	ljr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-javascript-report"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-javascript-report
 		;;
 	ljf)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-javascript-fix"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-javascript-fix
 		;;
 	pp)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS php-parserror"
+		run_devtools_in_docker "${CONTAINER_ID}" php-parserror
 		;;
 	ut)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS unit-test"
+		run_devtools_in_docker "${CONTAINER_ID}" unit-test
 		;;
 	jut)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS javascript-unit-test"
+		run_devtools_in_docker "${CONTAINER_ID}" javascript-unit-test
 		;;
 	jrb)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS jut-reports-build"
+		run_devtools_in_docker "${CONTAINER_ID}" jut-reports-build
 		;;
 	at)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS api-test"
+		run_devtools_in_docker "${CONTAINER_ID}" api-test
 		;;
 	et)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS e2e-test"
+		run_devtools_in_docker "${CONTAINER_ID}" e2e-test
 		;;
 	st)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS services-test"
+		run_devtools_in_docker "${CONTAINER_ID}" services-test
 		;;
 	ft)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS fixtures-test"
+		run_devtools_in_docker "${CONTAINER_ID}" fixtures-test
 		;;
 	vt)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS validators-test"
+		run_devtools_in_docker "${CONTAINER_ID}" validators-test
 		;;
 	ct)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS controllers-test"
+		run_devtools_in_docker "${CONTAINER_ID}" controllers-test
 		;;
 	ctt)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS common-test"
+		run_devtools_in_docker "${CONTAINER_ID}" common-test
 		;;
 	cs)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS clean-sweep"
+		run_devtools_in_docker "${CONTAINER_ID}" clean-sweep
 		;;
 	cst)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS clean-sweep-tests"
+		run_devtools_in_docker "${CONTAINER_ID}" clean-sweep-tests
 		;;
 	dr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-reset"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-reset
 		restart_couchdb_docker
 		;;
 	di)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-install"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-install
 		restart_couchdb_docker
 		;;
 	dri)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-reset-install"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-reset-install
 		restart_couchdb_docker
 		;;
 	drid)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-reset-install-demodata"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-reset-install-demodata
 		restart_couchdb_docker
 		;;
 	ls)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-snapshots"
+		run_devtools_in_docker "${CONTAINER_ID}" list-snapshots
 		;;
 	lc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-capsules"
+		run_devtools_in_docker "${CONTAINER_ID}" list-capsules
 		;;
 	em)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS enable-multisite"
+		run_devtools_in_docker "${CONTAINER_ID}" enable-multisite
 		;;
 	dm)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS disable-multisite"
+		run_devtools_in_docker "${CONTAINER_ID}" disable-multisite
 		;;
 	fh)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS force-https"
+		run_devtools_in_docker "${CONTAINER_ID}" force-https
 		;;
 	ufh)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS un-force-https"
+		run_devtools_in_docker "${CONTAINER_ID}" un-force-https
 		;;
 	ossc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS on-self-signed-cert"
+		run_devtools_in_docker "${CONTAINER_ID}" on-self-signed-cert
 		;;
 	lcc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-client-certs"
+		run_devtools_in_docker "${CONTAINER_ID}" list-client-certs
 		;;
 	ss)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl
 		;;
 	sso)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl-off"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl-off
 		;;
 	ssc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl-client"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl-client
 		;;
 	ssco)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl-client-off"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl-client-off
 		;;
 	css)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl
 		;;
 	cso)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl-off"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl-off
 		;;
 	csc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl-client"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl-client
 		;;
 	csco)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl-client-off"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl-client-off
 		;;
 	lss)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl
 		;;
 	lso)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl-off"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl-off
 		;;
 	lsc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl-client"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl-client
 		;;
 	lsco)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl-client-off"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl-client-off
 		;;
 	gmb|generate-multisite-bank)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS generate-multisite-bank $@"
+        # Pass remaining arguments ($@) correctly quoted to the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" generate-multisite-bank "$@"
 		;;
 	el)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS enable-ldap"
+		run_devtools_in_docker "${CONTAINER_ID}" enable-ldap
 		;;
 	dld)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS disable-ldap"
+		run_devtools_in_docker "${CONTAINER_ID}" disable-ldap
 		;;
 	xl)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS xdebug-log"
+		run_devtools_in_docker "${CONTAINER_ID}" xdebug-log
 		;;
 	lxp)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-xdebug-profiles"
+		run_devtools_in_docker "${CONTAINER_ID}" list-xdebug-profiles
 		;;
 	bad)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS build-api-docs"
+		run_devtools_in_docker "${CONTAINER_ID}" build-api-docs
 		;;
 	lm)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-multisites"
+		run_devtools_in_docker "${CONTAINER_ID}" list-multisites
 		;;
-
 	*)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS $FIRST_ARG"
+		# Default case: assume it's a devtools command
+		run_devtools_in_docker "${CONTAINER_ID}" "${FIRST_ARG}" "$@"
 		;;
 esac
-exit $FINAL_EXIT_CODE
+exit "${FINAL_EXIT_CODE}"
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: With `set -e` it's hard to be sure the script will exit with exactly this code unless we do a lot more review.
created_at: 2025-04-24T17:08:31Z
author_association: MEMBER
diff_hunk: @@ -321,125 +353,151 @@ then
   echo "  dpi, docker-pull-image             Prompt to pull docker image"
   echo 'php-management:'
   echo "  bt, build-themes                   Make changes to any files on your local file system"
-	echo "  pl, php-log                        To check PHP error logs"
-	echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
-	echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
-	echo "  ltr, lint-themes-report            To create a report of theme styling issues"
-	echo "  ltf, lint-themes-fix               To fix theme styling issues"
+  echo "  pl, php-log                        To check PHP error logs"
+  echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
+  echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
+  echo "  ltr, lint-themes-report            To create a report of theme styling issues"
+  echo "  ltf, lint-themes-fix               To fix theme styling issues"
   echo "  ljr, lint-javascript-report        To create a report of javascript styling issues"
   echo "  ljf, lint-javascript-fix           To fix javascript styling issues"
-	echo "  pp, php-parserror                  To check PHP parsing errors"
-	echo "  xl, xdebug-log                     To check xdebug log"
-	echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
+  echo "  pp, php-parserror                  To check PHP parsing errors"
+  echo "  xl, xdebug-log                     To check xdebug log"
+  echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
   echo 'test-management:'
-	echo "  ut, unit-test                      To run php unit testing"
-	echo "  jut, javascript-unit-test          To run javascript unit testing"
-	echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
-	echo "  at, api-test                       To run api testing"
-	echo "  et, e2e-test                       To run e2e testing"
-	echo "  st, services-test                  To run services testing"
-	echo "  ft, fixtures-test                  To run fixtures testing"
-	echo "  vt, validators-test                To run validators testing"
-	echo "  ct, controllers-test               To run controllers testing"
-	echo "  ctt, common-test                   To run common testing"
+  echo "  ut, unit-test                      To run php unit testing"
+  echo "  jut, javascript-unit-test          To run javascript unit testing"
+  echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
+  echo "  at, api-test                       To run api testing"
+  echo "  et, e2e-test                       To run e2e testing"
+  echo "  st, services-test                  To run services testing"
+  echo "  ft, fixtures-test                  To run fixtures testing"
+  echo "  vt, validators-test                To run validators testing"
+  echo "  ct, controllers-test               To run controllers testing"
+  echo "  ctt, common-test                   To run common testing"
   echo 'sweep-management:'
-	echo "  cs, clean-sweep                    To run the entire dev tool suite"
-	echo "  cst, clean-sweep-tests             To run only all the automated tests"
-  echo 'reset-mamagement:'
-	echo "  dr, dev-reset                      To reset OpenEMR only"
-	echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
-	echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
-	echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
+  echo "  cs, clean-sweep                    To run the entire dev tool suite"
+  echo "  cst, clean-sweep-tests             To run only all the automated tests"
+  echo 'reset-management:'
+  echo "  dr, dev-reset                      To reset OpenEMR only"
+  echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
+  echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
+  echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
   echo 'backup-management:'
-	echo "  bs, backup-snapshot                Create a backup snapshot"
-	echo "  rs, restore-snapshot               Restore from a snapshot"
-	echo "  ls, list-snapshots                 To list the snapshots"
-	echo "  lc, list-capsules                  List the capsules"
-	echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
-	echo "  pc, put-capsule                    Copy the capsule into the docker"
+  echo "  bs, backup-snapshot                Create a backup snapshot"
+  echo "  rs, restore-snapshot               Restore from a snapshot"
+  echo "  ls, list-snapshots                 To list the snapshots"
+  echo "  lc, list-capsules                  List the capsules"
+  echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
+  echo "  pc, put-capsule                    Copy the capsule into the docker"
   echo 'ssl-management:'
-	echo "  fh, force-https                    Force https"
-	echo "  ufh, un-force-https                Removing forcing of https"
-	echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
-	echo "  scc, setup-client-cert             Turn on client based cert with designated package"
-	echo "  lcc, list-client-certs             To list the certificate packages"
-	echo "  pcc, put-client-cert               To copy certificate package into the docker"
-	echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
+  echo "  fh, force-https                    Force https"
+  echo "  ufh, un-force-https                Removing forcing of https"
+  echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
+  echo "  scc, setup-client-cert             Turn on client based cert with designated package"
+  echo "  lcc, list-client-certs             To list the certificate packages"
+  echo "  pcc, put-client-cert               To copy certificate package into the docker"
+  echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
   echo "  sso, sql-ssl-off                   Remove testing sql ssl CA cert"
   echo "  ssc, sql-ssl-client                Use testing sql ssl client certs"
   echo "  ssco, sql-ssl-client-off           Remove testing sql ssl client certs"
-	echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
+  echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
   echo "  cso, couchdb-ssl-off               Remove testing couchdb ssl CA cert"
   echo "  csc, couchdb-ssl-client            Use testing couchdb ssl client certs"
   echo "  csco, couchdb-ssl-client-off       Remove testing couchdb ssl client certs"
-	echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
+  echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
   echo "  lso, ldap-ssl-off                  Remove testing ldap ssl CA cert"
   echo "  lsc, ldap-ssl-client               Use testing ldap ssl client certs"
   echo "  lsco, ldap-ssl-client-off          Remove testing ldap ssl client certs"
   echo 'multisite-management:'
   echo "  lm, list-multisites                List multisites"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
-	echo "  em, enable-multisite               Turn on support for multisite in setup.php"
-	echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  em, enable-multisite               Turn on support for multisite in setup.php"
+  echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
   echo 'api-management:'
   echo "  bad, build-api-docs                Build and place api documentation/configuration for swagger"
   echo "  roc, register-oauth2-client        Register oauth2 client (returns client id/secret)"
   echo "  rocd, register-oauth2-client-demo  Register oauth2 client (returns client id/secret) on online demo"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
   echo 'computational-health-informatics:'
-	echo "  irp, import-random-patients        Create and import random patients <number patients>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  irp, import-random-patients        Create and import random patients <number patients>"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
   echo 'webroot-management:'
-	echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
-	echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
+  echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
+  echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
   echo 'others:'
-	echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
-	echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
-	echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
-	echo "  ec, encoding-collation             Change the database character set and collation"
-
-	exit $USAGE_EXIT_CODE
-elif [ "$FIRST_ARG" == '--version' ] || [ "$FIRST_ARG" == '-v' ]
-then
-	echo "openemr-cmd $VERSION"
-	exit $VERSION_EXIT_CODE
+  echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
+  echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
+  echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
+  echo "  ec, encoding-collation             Change the database character set and collation"
+
+  exit "${USAGE_EXIT_CODE}"
+
+elif [[ "${FIRST_ARG}" == '--version' ]] || [[ "${FIRST_ARG}" == '-v' ]]; then
+	echo "openemr-cmd ${VERSION}"
+	exit "${VERSION_EXIT_CODE}"
 fi
 
 # Specify the docker id/name to execute the commands.
-#  default to insane dev docker, if exists
-CONTAINER_ID=$(docker ps | grep $INSANE_DEV_DOCKER | cut -f 1 -d " ")
-if [ -z $CONTAINER_ID ]
-then
-  # else, default to easy dev docker, if exists
-  CONTAINER_ID=$(docker ps | grep $EASY_DEV_DOCKER | cut -f 1 -d " ")
+# Default to insane dev docker, if exists, otherwise easy dev docker.
+# Try to find the insane dev docker ID directly
+if insane_id=$(docker ps --filter "name=${INSANE_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${insane_id}" ]]; then
+  CONTAINER_ID="${insane_id}"
+# Try to find the easy dev docker ID directly
+elif easy_id=$(docker ps --filter "name=${EASY_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${easy_id}" ]]; then
+  CONTAINER_ID="${easy_id}"
+else
+  # Neither container found running, set CONTAINER_ID to empty.
+  # The script's later logic handles the -d flag or errors if no container is specified.
+  CONTAINER_ID=""
 fi
+
 # override the default container setting if supplied via the -d parameter
 #  (also removing no longer needed parameters via shift)
 CHANGE_CONTAINER_CODE=25
-if [ "$FIRST_ARG" == '-d' ] && [ $# -ge 3 ]
-then
-	CONTAINER_ID=$2
-	FIRST_ARG=$3
+if [[ "${FIRST_ARG}" == '-d' ]] && [[ $# -ge 3 ]]; then
+	CONTAINER_ID="$2"
+	FIRST_ARG="$3"
 	shift 3
-elif [ "$FIRST_ARG" == '-d' ] && [ $# -lt 3 ]
-then
+elif [[ "${FIRST_ARG}" == '-d' ]] && [[ $# -lt 3 ]]; then
 	echo 'Please provide a docker id/name when using -d parameter.'
 	echo 'e.g. openemr-cmd -d docker_openemr-7-3-redis-312_1 dl'
-	exit $CHANGE_CONTAINER_CODE
+	exit "${CHANGE_CONTAINER_CODE}"
 else
   shift
 fi
 
 #collect the couchdb docker name
-COUCHDB_CONTAINER=$(docker ps | grep $COUCHDB_DOCKER | cut -f 1 -d " ")
+# Use docker ps --filter and --format for efficiency and robustness
+couchdb_id=$(docker ps --filter "name=${COUCHDB_DOCKER}" --format "{{.ID}}" | head -n 1)
+COUCHDB_CONTAINER="${couchdb_id:-}" # Set to empty if not found
 
 # Collect the mariadb container id
-MARIADB_CONTAINER_ID=$(docker ps | grep $MARIADB_DOCKER | cut -f 1 -d " ")
+# Use docker ps --filter and --format for efficiency and robustness
+mariadb_id=$(docker ps --filter "name=${MARIADB_DOCKER}" --format "{{.ID}}" | head -n 1)
+MARIADB_CONTAINER_ID="${mariadb_id:-}" # Set to empty if not found
+
+# Check if a target container ID was determined or provided before proceeding with commands that need it
+# (Allow proceeding if the command doesn't require a container, like up, down, start, stop, --help, --version)
+case "${FIRST_ARG}" in
+  up|down|start|stop|--help|-h|--version|-v)
+    # These commands don't necessarily need a running container ID determined here
+    ;;
+  *)
+    # All other commands likely need a CONTAINER_ID
+    # Check if CONTAINER_ID is empty AND -d wasn't the *original* first arg
+    if [[ -z "${CONTAINER_ID}" ]] && [[ "${FIRST_ARG}" != '-d' ]]; then
+      echo "Error: Could not automatically determine target OpenEMR container (tried '${INSANE_DEV_DOCKER}' and '${EASY_DEV_DOCKER}')." >&2
+      echo "Use -d <container_name_or_id> to specify the target container." >&2
+      exit 1
+    fi
+    # If -d was used, CONTAINER_ID was set in the parameter parsing block
+    ;;
+esac
 
 # See how we were called.
 # For the shift usage, it used to cover the insane env.
-case "$FIRST_ARG" in
+case "${FIRST_ARG}" in
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: This `case` expression looks like it would benefit from an associative array.
created_at: 2025-04-24T17:09:03Z
author_association: MEMBER
diff_hunk: @@ -24,267 +30,292 @@ get_container_names() {
 # Set the container names
 get_container_names
 
+# Function to run the devtools script inside the specified container
+# Usage: run_devtools_in_docker <container_id> <devtools_command> [args...]
+run_devtools_in_docker() {
+  local container_id="$1"
+  shift # Remove container_id from arguments
+  # DEV_TOOLS is '/root/devtools'
+  # "$@" passes the remaining arguments (devtools command and its args) correctly quoted
+  docker exec -i "${container_id}" "${DEV_TOOLS}" "$@"
+}
+
+# Function to run an arbitrary shell command string inside the specified container
+# Usage: run_shell_command_in_docker <container_id> <command_string>
+run_shell_command_in_docker() {
+  local container_id="$1"
+  local command_string="$2"
+  docker exec -i "${container_id}" sh -c "${command_string}"
+}
+
 # Set some constants
-DOCKER_EXEC_CMD='docker exec -i'                                 # docker exec command
-SHELL_TYPE='sh -c'                                               # specify shell type
-FIRST_ARG=$1											                               # define the first parameter
-DEV_TOOLS=/root/devtools
+FIRST_ARG="${1:-}" # define the first parameter, default to empty if not set
+DEV_TOOLS='/root/devtools'
 
 check_docker_compose_install_or_not(){
-	DOCKER_COMPOSE_CODE=22
-	which docker-compose &>/dev/null
-	[ $? -ne 0 ] && echo "Please check docker-compose install or not." && exit $DOCKER_COMPOSE_CODE
+	local DOCKER_COMPOSE_CODE=22
path: utilities/openemr-cmd/openemr-cmd
user: login: msummers42
body: Just made a change that should address that specific area. Lots of mixing of tabs & spaces in here.
created_at: 2025-04-24T18:08:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -24,267 +30,292 @@ get_container_names() {
 # Set the container names
 get_container_names
 
+# Function to run the devtools script inside the specified container
+# Usage: run_devtools_in_docker <container_id> <devtools_command> [args...]
+run_devtools_in_docker() {
+  local container_id="$1"
+  shift # Remove container_id from arguments
+  # DEV_TOOLS is '/root/devtools'
+  # "$@" passes the remaining arguments (devtools command and its args) correctly quoted
+  docker exec -i "${container_id}" "${DEV_TOOLS}" "$@"
+}
+
+# Function to run an arbitrary shell command string inside the specified container
+# Usage: run_shell_command_in_docker <container_id> <command_string>
+run_shell_command_in_docker() {
+  local container_id="$1"
+  local command_string="$2"
+  docker exec -i "${container_id}" sh -c "${command_string}"
+}
+
 # Set some constants
-DOCKER_EXEC_CMD='docker exec -i'                                 # docker exec command
-SHELL_TYPE='sh -c'                                               # specify shell type
-FIRST_ARG=$1											                               # define the first parameter
-DEV_TOOLS=/root/devtools
+FIRST_ARG="${1:-}" # define the first parameter, default to empty if not set
+DEV_TOOLS='/root/devtools'
 
 check_docker_compose_install_or_not(){
-	DOCKER_COMPOSE_CODE=22
-	which docker-compose &>/dev/null
-	[ $? -ne 0 ] && echo "Please check docker-compose install or not." && exit $DOCKER_COMPOSE_CODE
+	local DOCKER_COMPOSE_CODE=22
+	if ! command -v docker-compose &>/dev/null; then
+		echo "Please check docker-compose install or not."
+    exit "${DOCKER_COMPOSE_CODE}"
+	fi
 }
 
 quick_open_a_docker_shell(){
-  docker exec -w /var/www/localhost/htdocs/openemr -it $CONTAINER_ID sh
+  docker exec -w /var/www/localhost/htdocs/openemr -it "${CONTAINER_ID}" sh
 }
 
 quick_open_a_maria_docker_shell(){
-  docker exec -it $MARIADB_CONTAINER_ID /bin/bash
+  docker exec -it "${MARIADB_CONTAINER_ID}" /bin/bash
 }
 
 execute_command_flexible(){
-	if [ $# -lt 1 ]
-	then
+	if [[ $# -lt 1 ]]; then
 		echo "Please provide the command."
-		echo "e.g. `basename $0` [exec|e] \"tail -f /var/log/apache2/error.log\""
-		echo "e.g. `basename $0` -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$@"
+		# Use the function for arbitrary commands
+		run_shell_command_in_docker "${CONTAINER_ID}" "$@"
 	fi
 }
 
 check_docker_log() {
-  docker logs $CONTAINER_ID
+  docker logs "${CONTAINER_ID}"
 }
 
 check_docker_names() {
-	CHECK_NAME=$1     # specify the checking name
-	if [ $# -eq 1 ]
-	then
+	if [[ $# -eq 1 ]]; then
 		# ARGS: couchdb php fhir mariadb mysql nginx openemr openldap orthanc redis.
+        # specify the name to check
+        local CHECK_NAME="$1"
 		echo '===Check the single Docker Name==='
 		echo '  STATUS        NAME'
-		docker ps -a --format "{{.Status}}\t{{.Names}}"| grep $CHECK_NAME
+        # Capture output, check if empty
+        local matching_container
+        matching_container=$(docker ps -a --format "{{.Status}}\t{{.Names}}"| grep "${CHECK_NAME}" || true) # Keep || true here, and below, to prevent exit during capture
+        if [[ -z "${matching_container}" ]]; then
+            echo "No containers found matching '${CHECK_NAME}'"
+        else
+            echo "${matching_container}"
+        fi
 
 	else
 		# Show all the docker names.
 		echo '***************************************************************'
 		echo 'Show all the docker names by default.'
 		echo 'Please provide the keyword if you want to check the single one.'
-		echo "e.g `basename $0` [docker-names|dn] php"
+		echo "e.g $(basename "$0") [docker-names|dn] php"
 		echo '***************************************************************'
 		echo '=======Running Docker Names======='
-		docker ps | awk '{print $NF}'|grep -v NAMES|sort -n
+		
+        # Capture output, check if empty
+        local running_containers
+        running_containers=$(docker ps --format "{{.Status}}\t{{.Names}}" | { grep -v NAMES || true; } | sort -n)
+        if [[ -z "${running_containers}" ]]; then
+            echo "No running containers found."
+        else
+		    echo '  STATUS        NAME'
+            echo "${running_containers}"
+        fi
 		echo '====Other Docker Status Names====='
-		docker ps -a --format "table{{.Status}}\t{{.Names}}"| grep -v Up
+        # Capture output, check if empty
+        local other_containers
+        other_containers=$(docker ps -a --format "{{.Status}}\t{{.Names}}" | grep -v Up || true)
+        if [[ -z "${other_containers}" ]]; then
+            echo "No containers found with other statuses."
+        else
+		    echo '  STATUS        NAME'
+            echo "${other_containers}"
+        fi
 	fi
 }
 
 restart_couchdb_docker(){
-  if [ -z "$COUCHDB_CONTAINER" ]
-  then
+  if [[ -z "${COUCHDB_CONTAINER}" ]]; then
     echo "Unable to find the couchdb docker, so could not restart it"
   else
     echo "Restarting couchdb docker"
-    docker restart "$COUCHDB_CONTAINER"
+    docker restart "${COUCHDB_CONTAINER}"
   fi
 }
 
 creat_a_backup_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=20
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=20
+    if [[ $# != 1 ]]; then
 		echo 'Please provide a snapshot name.'
 		echo 'e.g. openemr-cmd [backup-snapshot|bs] example'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS backup $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" backup "${BACKUP_FILE}"
 	fi
 }
 
 restore_from_a_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=21
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=21
+    if [[ $# != 1 ]]; then
         echo 'Please provide a restore snapshot name.'
         echo 'e.g. openemr-cmd [restore-snapshot|rs] example'
-        exit $BACKUP_FILE_CODE
+        exit "${BACKUP_FILE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS restore $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" restore "${BACKUP_FILE}"
 	fi
 }
 
 copy_capsule_from_docker_to_host(){
-	BACKUP_FILE=$1
-	BACKUP_HOST_DIR=$2 #optional parameter
-	BACKUP_FILE_CODE=19
-	if [ $# != 1 ] && [ $# != 2 ]
-	then
+	local BACKUP_FILE="$1"
+	local BACKUP_HOST_DIR="${2:-}" #optional parameter, default to empty
+	local BACKUP_FILE_CODE=19
+	if [[ $# != 1 ]] && [[ $# != 2 ]]; then
path: utilities/openemr-cmd/openemr-cmd
user: login: msummers42
body: I just made a style change, not logic.
created_at: 2025-04-24T18:09:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -496,190 +554,191 @@ case "$FIRST_ARG" in
 	pcc|put-client-cert)
 		put-client-cert "$@"
 		;;
-  irp|import-random-patients)
-    import-random-patients "$@"
-		;;
-  rocd|register-oauth2-client-demo)
-    register-oauth2-client-demo "$@"
-		;;
-  roc|register-oauth2-client)
-    register-oauth2-client "$@"
-		;;
-  swtm|set-swagger-to-multisite)
-    set-swagger-to-multisite "$@"
-		;;
-  cwb|change-webroot-blank)
-    set-webroot
-		;;
-  cwo|change-webroot-openemr)
-    set-webroot openemr
-		;;
-  ms|maria-shell)
-    quick_open_a_maria_docker_shell
-		;;
+    irp|import-random-patients)
+        import-random-patients "$@"
+        ;;
+    rocd|register-oauth2-client-demo)
+        register-oauth2-client-demo "$@"
+        ;;
+    roc|register-oauth2-client)
+        register-oauth2-client "$@"
+        ;;
+    swtm|set-swagger-to-multisite)
+        set-swagger-to-multisite "$@"
+        ;;
+    cwb|change-webroot-blank)
+        set-webroot
+        ;;
+    cwo|change-webroot-openemr)
+        set-webroot openemr
+        ;;
+    ms|maria-shell)
+        quick_open_a_maria_docker_shell
+        ;;
 	bt)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS build-themes"
+		run_devtools_in_docker "${CONTAINER_ID}" build-themes
 		;;
 	pl)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS php-log"
+		run_devtools_in_docker "${CONTAINER_ID}" php-log
 		;;
 	pr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS psr12-report"
+		run_devtools_in_docker "${CONTAINER_ID}" psr12-report
 		;;
 	pf)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS psr12-fix"
+		run_devtools_in_docker "${CONTAINER_ID}" psr12-fix
 		;;
 	ltr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-themes-report"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-themes-report
 		;;
 	ltf)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-themes-fix"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-themes-fix
 		;;
 	ljr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-javascript-report"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-javascript-report
 		;;
 	ljf)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS lint-javascript-fix"
+		run_devtools_in_docker "${CONTAINER_ID}" lint-javascript-fix
 		;;
 	pp)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS php-parserror"
+		run_devtools_in_docker "${CONTAINER_ID}" php-parserror
 		;;
 	ut)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS unit-test"
+		run_devtools_in_docker "${CONTAINER_ID}" unit-test
 		;;
 	jut)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS javascript-unit-test"
+		run_devtools_in_docker "${CONTAINER_ID}" javascript-unit-test
 		;;
 	jrb)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS jut-reports-build"
+		run_devtools_in_docker "${CONTAINER_ID}" jut-reports-build
 		;;
 	at)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS api-test"
+		run_devtools_in_docker "${CONTAINER_ID}" api-test
 		;;
 	et)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS e2e-test"
+		run_devtools_in_docker "${CONTAINER_ID}" e2e-test
 		;;
 	st)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS services-test"
+		run_devtools_in_docker "${CONTAINER_ID}" services-test
 		;;
 	ft)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS fixtures-test"
+		run_devtools_in_docker "${CONTAINER_ID}" fixtures-test
 		;;
 	vt)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS validators-test"
+		run_devtools_in_docker "${CONTAINER_ID}" validators-test
 		;;
 	ct)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS controllers-test"
+		run_devtools_in_docker "${CONTAINER_ID}" controllers-test
 		;;
 	ctt)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS common-test"
+		run_devtools_in_docker "${CONTAINER_ID}" common-test
 		;;
 	cs)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS clean-sweep"
+		run_devtools_in_docker "${CONTAINER_ID}" clean-sweep
 		;;
 	cst)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS clean-sweep-tests"
+		run_devtools_in_docker "${CONTAINER_ID}" clean-sweep-tests
 		;;
 	dr)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-reset"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-reset
 		restart_couchdb_docker
 		;;
 	di)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-install"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-install
 		restart_couchdb_docker
 		;;
 	dri)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-reset-install"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-reset-install
 		restart_couchdb_docker
 		;;
 	drid)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS dev-reset-install-demodata"
+		run_devtools_in_docker "${CONTAINER_ID}" dev-reset-install-demodata
 		restart_couchdb_docker
 		;;
 	ls)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-snapshots"
+		run_devtools_in_docker "${CONTAINER_ID}" list-snapshots
 		;;
 	lc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-capsules"
+		run_devtools_in_docker "${CONTAINER_ID}" list-capsules
 		;;
 	em)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS enable-multisite"
+		run_devtools_in_docker "${CONTAINER_ID}" enable-multisite
 		;;
 	dm)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS disable-multisite"
+		run_devtools_in_docker "${CONTAINER_ID}" disable-multisite
 		;;
 	fh)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS force-https"
+		run_devtools_in_docker "${CONTAINER_ID}" force-https
 		;;
 	ufh)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS un-force-https"
+		run_devtools_in_docker "${CONTAINER_ID}" un-force-https
 		;;
 	ossc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS on-self-signed-cert"
+		run_devtools_in_docker "${CONTAINER_ID}" on-self-signed-cert
 		;;
 	lcc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-client-certs"
+		run_devtools_in_docker "${CONTAINER_ID}" list-client-certs
 		;;
 	ss)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl
 		;;
 	sso)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl-off"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl-off
 		;;
 	ssc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl-client"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl-client
 		;;
 	ssco)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS sql-ssl-client-off"
+		run_devtools_in_docker "${CONTAINER_ID}" sql-ssl-client-off
 		;;
 	css)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl
 		;;
 	cso)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl-off"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl-off
 		;;
 	csc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl-client"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl-client
 		;;
 	csco)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS couchdb-ssl-client-off"
+		run_devtools_in_docker "${CONTAINER_ID}" couchdb-ssl-client-off
 		;;
 	lss)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl
 		;;
 	lso)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl-off"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl-off
 		;;
 	lsc)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl-client"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl-client
 		;;
 	lsco)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS ldap-ssl-client-off"
+		run_devtools_in_docker "${CONTAINER_ID}" ldap-ssl-client-off
 		;;
 	gmb|generate-multisite-bank)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS generate-multisite-bank $@"
+        # Pass remaining arguments ($@) correctly quoted to the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" generate-multisite-bank "$@"
 		;;
 	el)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS enable-ldap"
+		run_devtools_in_docker "${CONTAINER_ID}" enable-ldap
 		;;
 	dld)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS disable-ldap"
+		run_devtools_in_docker "${CONTAINER_ID}" disable-ldap
 		;;
 	xl)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS xdebug-log"
+		run_devtools_in_docker "${CONTAINER_ID}" xdebug-log
 		;;
 	lxp)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-xdebug-profiles"
+		run_devtools_in_docker "${CONTAINER_ID}" list-xdebug-profiles
 		;;
 	bad)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS build-api-docs"
+		run_devtools_in_docker "${CONTAINER_ID}" build-api-docs
 		;;
 	lm)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS list-multisites"
+		run_devtools_in_docker "${CONTAINER_ID}" list-multisites
 		;;
-
 	*)
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS $FIRST_ARG"
+		# Default case: assume it's a devtools command
+		run_devtools_in_docker "${CONTAINER_ID}" "${FIRST_ARG}" "$@"
 		;;
 esac
-exit $FINAL_EXIT_CODE
+exit "${FINAL_EXIT_CODE}"
path: utilities/openemr-cmd/openemr-cmd
user: login: msummers42
body: I agree, but `set -e` was in place already and I simply added the unbound var and pipefail bits. I think it's probably OK for the moment.
created_at: 2025-04-24T18:19:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -69,5 +76,9 @@ case "$FIRST_ARG" in
 		openemr-cmd -h
 		;;
 		*)
-		openemr-cmd -h|grep -i $FIRST_ARG
+		# Quoted variable
+		openemr-cmd -h | grep -i "${FIRST_ARG}"
+		;;
 esac
+
+exit 0 # Explicit success exit at end of script
path: utilities/openemr-cmd/openemr-cmd-h
user: login: msummers42
body: I just added that to be clear what exist status was used since there are a bunch of custom statuses set in various places in the scripts. It's not necessary.
created_at: 2025-04-24T18:21:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -24,267 +30,292 @@ get_container_names() {
 # Set the container names
 get_container_names
 
+# Function to run the devtools script inside the specified container
+# Usage: run_devtools_in_docker <container_id> <devtools_command> [args...]
+run_devtools_in_docker() {
+  local container_id="$1"
+  shift # Remove container_id from arguments
+  # DEV_TOOLS is '/root/devtools'
+  # "$@" passes the remaining arguments (devtools command and its args) correctly quoted
+  docker exec -i "${container_id}" "${DEV_TOOLS}" "$@"
+}
+
+# Function to run an arbitrary shell command string inside the specified container
+# Usage: run_shell_command_in_docker <container_id> <command_string>
+run_shell_command_in_docker() {
+  local container_id="$1"
+  local command_string="$2"
+  docker exec -i "${container_id}" sh -c "${command_string}"
+}
+
 # Set some constants
-DOCKER_EXEC_CMD='docker exec -i'                                 # docker exec command
-SHELL_TYPE='sh -c'                                               # specify shell type
-FIRST_ARG=$1											                               # define the first parameter
-DEV_TOOLS=/root/devtools
+FIRST_ARG="${1:-}" # define the first parameter, default to empty if not set
+DEV_TOOLS='/root/devtools'
 
 check_docker_compose_install_or_not(){
-	DOCKER_COMPOSE_CODE=22
-	which docker-compose &>/dev/null
-	[ $? -ne 0 ] && echo "Please check docker-compose install or not." && exit $DOCKER_COMPOSE_CODE
+	local DOCKER_COMPOSE_CODE=22
+	if ! command -v docker-compose &>/dev/null; then
+		echo "Please check docker-compose install or not."
+    exit "${DOCKER_COMPOSE_CODE}"
+	fi
 }
 
 quick_open_a_docker_shell(){
-  docker exec -w /var/www/localhost/htdocs/openemr -it $CONTAINER_ID sh
+  docker exec -w /var/www/localhost/htdocs/openemr -it "${CONTAINER_ID}" sh
 }
 
 quick_open_a_maria_docker_shell(){
-  docker exec -it $MARIADB_CONTAINER_ID /bin/bash
+  docker exec -it "${MARIADB_CONTAINER_ID}" /bin/bash
 }
 
 execute_command_flexible(){
-	if [ $# -lt 1 ]
-	then
+	if [[ $# -lt 1 ]]; then
 		echo "Please provide the command."
-		echo "e.g. `basename $0` [exec|e] \"tail -f /var/log/apache2/error.log\""
-		echo "e.g. `basename $0` -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") [exec|e] \"tail -f /var/log/apache2/error.log\""
+		echo "e.g. $(basename "$0") -d docker_openemr-7-3-redis-312_1 [exec|e] \"tail -f /var/log/apache2/error.log\""
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$@"
+		# Use the function for arbitrary commands
+		run_shell_command_in_docker "${CONTAINER_ID}" "$@"
 	fi
 }
 
 check_docker_log() {
-  docker logs $CONTAINER_ID
+  docker logs "${CONTAINER_ID}"
 }
 
 check_docker_names() {
-	CHECK_NAME=$1     # specify the checking name
-	if [ $# -eq 1 ]
-	then
+	if [[ $# -eq 1 ]]; then
 		# ARGS: couchdb php fhir mariadb mysql nginx openemr openldap orthanc redis.
+        # specify the name to check
+        local CHECK_NAME="$1"
 		echo '===Check the single Docker Name==='
 		echo '  STATUS        NAME'
-		docker ps -a --format "{{.Status}}\t{{.Names}}"| grep $CHECK_NAME
+        # Capture output, check if empty
+        local matching_container
+        matching_container=$(docker ps -a --format "{{.Status}}\t{{.Names}}"| grep "${CHECK_NAME}" || true) # Keep || true here, and below, to prevent exit during capture
+        if [[ -z "${matching_container}" ]]; then
+            echo "No containers found matching '${CHECK_NAME}'"
+        else
+            echo "${matching_container}"
+        fi
 
 	else
 		# Show all the docker names.
 		echo '***************************************************************'
 		echo 'Show all the docker names by default.'
 		echo 'Please provide the keyword if you want to check the single one.'
-		echo "e.g `basename $0` [docker-names|dn] php"
+		echo "e.g $(basename "$0") [docker-names|dn] php"
 		echo '***************************************************************'
 		echo '=======Running Docker Names======='
-		docker ps | awk '{print $NF}'|grep -v NAMES|sort -n
+		
+        # Capture output, check if empty
+        local running_containers
+        running_containers=$(docker ps --format "{{.Status}}\t{{.Names}}" | { grep -v NAMES || true; } | sort -n)
+        if [[ -z "${running_containers}" ]]; then
+            echo "No running containers found."
+        else
+		    echo '  STATUS        NAME'
+            echo "${running_containers}"
+        fi
 		echo '====Other Docker Status Names====='
-		docker ps -a --format "table{{.Status}}\t{{.Names}}"| grep -v Up
+        # Capture output, check if empty
+        local other_containers
+        other_containers=$(docker ps -a --format "{{.Status}}\t{{.Names}}" | grep -v Up || true)
+        if [[ -z "${other_containers}" ]]; then
+            echo "No containers found with other statuses."
+        else
+		    echo '  STATUS        NAME'
+            echo "${other_containers}"
+        fi
 	fi
 }
 
 restart_couchdb_docker(){
-  if [ -z "$COUCHDB_CONTAINER" ]
-  then
+  if [[ -z "${COUCHDB_CONTAINER}" ]]; then
     echo "Unable to find the couchdb docker, so could not restart it"
   else
     echo "Restarting couchdb docker"
-    docker restart "$COUCHDB_CONTAINER"
+    docker restart "${COUCHDB_CONTAINER}"
   fi
 }
 
 creat_a_backup_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=20
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=20
+    if [[ $# != 1 ]]; then
 		echo 'Please provide a snapshot name.'
 		echo 'e.g. openemr-cmd [backup-snapshot|bs] example'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS backup $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" backup "${BACKUP_FILE}"
 	fi
 }
 
 restore_from_a_snapshot(){
-    BACKUP_FILE=$1
-    BACKUP_FILE_CODE=21
-    if [ $# != 1 ]
-    then
+    local BACKUP_FILE="$1"
+    local BACKUP_FILE_CODE=21
+    if [[ $# != 1 ]]; then
         echo 'Please provide a restore snapshot name.'
         echo 'e.g. openemr-cmd [restore-snapshot|rs] example'
-        exit $BACKUP_FILE_CODE
+        exit "${BACKUP_FILE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS restore $BACKUP_FILE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" restore "${BACKUP_FILE}"
 	fi
 }
 
 copy_capsule_from_docker_to_host(){
-	BACKUP_FILE=$1
-	BACKUP_HOST_DIR=$2 #optional parameter
-	BACKUP_FILE_CODE=19
-	if [ $# != 1 ] && [ $# != 2 ]
-	then
+	local BACKUP_FILE="$1"
+	local BACKUP_HOST_DIR="${2:-}" #optional parameter, default to empty
+	local BACKUP_FILE_CODE=19
+	if [[ $# != 1 ]] && [[ $# != 2 ]]; then
 		echo 'Please provide the capsule name.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz'
 		echo 'An optional setting is the path to save to. If nothing provided, then will save in current directory.'
 		echo 'e.g. openemr-cmd [get-capsule|gc] example.tgz /path/to/save'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-	  if [ -z "$BACKUP_HOST_DIR" ]
-	  then
-		  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE .
+	  if [[ -z "${BACKUP_HOST_DIR}" ]]; then
+		  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" .
     else
-      	  docker cp ${CONTAINER_ID}:/snapshots/$BACKUP_FILE "${BACKUP_HOST_DIR}/"
+      	  docker cp "${CONTAINER_ID}:/snapshots/${BACKUP_FILE}" "${BACKUP_HOST_DIR}/"
     fi
 	fi
 }
 
 copy_capsule_from_host_to_docker(){
 	# Need a capsule parameter
-	BACKUP_FILE=$1
-	CP_CAP_DIR_DKR_CODE=15
-	BACKUP_FILE_CODE=18
-	if [ $# != 1 ]
-	then
+	local BACKUP_FILE="$1"
+	local CP_CAP_DIR_DKR_CODE=15
+	local BACKUP_FILE_CODE=18
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the capsule file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [put-capsule|pc] example.tgz'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-		ls $BACKUP_FILE  &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${BACKUP_FILE}" &>/dev/null; then
 			echo 'Please check whether the capsule file exists or not'
-			exit $CP_CAP_DIR_DKR_CODE
+			exit "${CP_CAP_DIR_DKR_CODE}"
 		else
-			docker cp $BACKUP_FILE  ${CONTAINER_ID}:/snapshots/
+			docker cp "${BACKUP_FILE}" "${CONTAINER_ID}:/snapshots/"
 		fi
 	fi
 }
 
 ensure_current_ver_with_upgrade_ver(){
   # Need a version parameter
-  UPGRADE_FROM_VERSION=$1
-  BACKUP_FILE_CODE=22
-	if [ $# != 1 ]
-	then
+  local UPGRADE_FROM_VERSION="$1"
+  local BACKUP_FILE_CODE=22
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the OpenEMR version to upgrade database from.'
 		echo 'e.g. openemr-cmd [ensure-version|ev] 5.0.2'
-		exit $BACKUP_FILE_CODE
+		exit "${BACKUP_FILE_CODE}"
 	else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS upgrade ${UPGRADE_FROM_VERSION}"
+    # Use the devtools function
+    run_devtools_in_docker "${CONTAINER_ID}" upgrade "${UPGRADE_FROM_VERSION}"
 	fi
 }
 
 change_db_character_set_and_collation(){
-	CHARACTER_SET_COLLATION_CODE=17
-	if [ $# != 2 ]
-	then
+	local CHARACTER_SET_COLLATION_CODE=17
+	if [[ $# != 2 ]]; then
 		echo 'Please provide two parameters.'
 		echo 'e.g. openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_general_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_unicode_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8mb4 utf8mb4_vietnamese_ci'
 		echo '     openemr-cmd [encoding-collation|ec] utf8 utf8_general_ci'
-		exit $CHARACTER_SET_COLLATION_CODE
+		exit "${CHARACTER_SET_COLLATION_CODE}"
 	else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS change-encoding-collation $1 $2"
+		# Use the devtools function, passing both arguments
+		run_devtools_in_docker "${CONTAINER_ID}" change-encoding-collation "$1" "$2"
 	fi
 }
 
 setup-client-cert(){
-    CERT_PACKAGE=$1
-    CERT_PACKAGE_CODE=30
-    if [ $# != 1 ]
-    then
+    local CERT_PACKAGE="$1"
+    local CERT_PACKAGE_CODE=30
+    if [[ $# != 1 ]]; then
         echo 'Please provide a certificate package name.'
         echo 'e.g. openemr-cmd [scc|setup-client-cert] sll'
-        exit $CERT_PACKAGE_CODE
+        exit "${CERT_PACKAGE_CODE}"
     else
-		$DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS setup-client-cert $CERT_PACKAGE"
+		# Use the devtools function
+		run_devtools_in_docker "${CONTAINER_ID}" setup-client-cert "${CERT_PACKAGE}"
 	fi
 }
 
 put-client-cert(){
 	# Need a capsule parameter
-	CERT_PACKAGE_FILE=$1
-	PUT_CLIENT_CERT_CODE=32
-	CERT_PACKAGE_FILE_CODE=31
-	if [ $# != 1 ]
-	then
+	local CERT_PACKAGE_FILE="$1"
+	local PUT_CLIENT_CERT_CODE=32
+	local CERT_PACKAGE_FILE_CODE=31
+	if [[ $# != 1 ]]; then
 		echo 'Please provide the certificate package file name (including path if applicable).'
 		echo 'e.g. openemr-cmd [pcc|put-client-cert] sll.zip'
-		exit $CERT_PACKAGE_FILE_CODE
+		exit "${CERT_PACKAGE_FILE_CODE}"
 	else
-		ls $CERT_PACKAGE_FILE &>/dev/null
-		if [ $? -ne 0 ]
-		then
+		if ! ls "${CERT_PACKAGE_FILE}" &>/dev/null; then
 			echo 'Please check whether the certificate package file exists or not'
-			exit $PUT_CLIENT_CERT_CODE
+			exit "${PUT_CLIENT_CERT_CODE}"
 		else
-			docker cp $CERT_PACKAGE_FILE ${CONTAINER_ID}:/certs/
+			docker cp "${CERT_PACKAGE_FILE}" "${CONTAINER_ID}:/certs/"
 		fi
 	fi
 }
 
 import-random-patients(){
-  if [ $# == 2 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1 $2"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS import-random-patients $1"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" import-random-patients "$@"
 }
 
 register-oauth2-client-demo(){
-  $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client-demo $1"
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client-demo "$@"
 }
 
 register-oauth2-client(){
-  if [ $# == 1 ]
-  then
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client $1"
-  else
-    $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS register-oauth2-client"
-  fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" register-oauth2-client "$@"
 }
 
 set-swagger-to-multisite(){
-    if [ $# == 1 ]
-    then
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite $1"
-    else
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "$DEV_TOOLS set-swagger-to-multisite"
-    fi
+  # Use the devtools function, passing all arguments ($@)
+  run_devtools_in_docker "${CONTAINER_ID}" set-swagger-to-multisite "$@"
 }
 
 set-webroot(){
-    if [ $# == 1 ]
-    then
+    local sed_command
+    if [[ $# == 1 ]]; then
       # assume the openemr parameter was given, so set openemr webroot
       echo "changing webroot to openemr"
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs@g' /etc/apache2/conf.d/openemr.conf"
+      sed_command="sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs@g' /etc/apache2/conf.d/openemr.conf"
     else
       # set to blank, so set blank webroot
       echo "changing webroot to blank"
-      $DOCKER_EXEC_CMD $CONTAINER_ID $SHELL_TYPE "sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs/openemr@g' /etc/apache2/conf.d/openemr.conf"
+      sed_command="sed -i 's@^DocumentRoot /var/www/localhost/htdocs.*@DocumentRoot /var/www/localhost/htdocs/openemr@g' /etc/apache2/conf.d/openemr.conf"
     fi
+    # Use the function for arbitrary commands
+    run_shell_command_in_docker "${CONTAINER_ID}" "${sed_command}"
     # restart the docker
     echo "restarting openemr docker so the apache configuration change will take effect"
-    docker restart "$CONTAINER_ID"
+    docker restart "${CONTAINER_ID}"
 }
 
 docker-pull-image(){
+    local docker_images
     docker_images=$(docker ps --format "table {{.Image}}")
-    for IMAGE in $docker_images
-    do
-    if [ $IMAGE != "IMAGE" ] 
-    then
-      read -e -p "Do you wish to pull $IMAGE ? (y) " RESP
-      if [ "$RESP" = "y" ]; then 
-        docker pull "$IMAGE";
-      else 
-        echo "Skipping $IMAGE";
+    local IMAGE RESP
+    for IMAGE in ${docker_images}; do
+      if [[ "${IMAGE}" != "IMAGE" ]]; then
+        # Use -r with read
+        read -r -e -p "Do you wish to pull ${IMAGE} ? (y) " RESP
path: utilities/openemr-cmd/openemr-cmd
user: login: msummers42
body: Just using what was there, though I added the `-r` to avoid escape garbage.
created_at: 2025-04-24T18:24:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,16 +1,22 @@
 #!/bin/bash
+
+# Exit on error, unset var, pipe failure
+set -euo pipefail
path: utilities/openemr-cmd/openemr-cmd
user: login: msummers42
body: It's very noisy, and I suggested adding that when debugging versus standard usage. It might be interesting to add a debug flag that would `set -x`. I was thinking about adding one of the standard `die_msg()` that would print more debugging info at some point. 
created_at: 2025-04-24T18:25:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -321,125 +353,151 @@ then
   echo "  dpi, docker-pull-image             Prompt to pull docker image"
   echo 'php-management:'
   echo "  bt, build-themes                   Make changes to any files on your local file system"
-	echo "  pl, php-log                        To check PHP error logs"
-	echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
-	echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
-	echo "  ltr, lint-themes-report            To create a report of theme styling issues"
-	echo "  ltf, lint-themes-fix               To fix theme styling issues"
+  echo "  pl, php-log                        To check PHP error logs"
+  echo "  pr, psr12-report                   To create a report of PSR12 code styling issues"
+  echo "  pf, psr12-fix                      To fix PSR12 code styling issues"
+  echo "  ltr, lint-themes-report            To create a report of theme styling issues"
+  echo "  ltf, lint-themes-fix               To fix theme styling issues"
   echo "  ljr, lint-javascript-report        To create a report of javascript styling issues"
   echo "  ljf, lint-javascript-fix           To fix javascript styling issues"
-	echo "  pp, php-parserror                  To check PHP parsing errors"
-	echo "  xl, xdebug-log                     To check xdebug log"
-	echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
+  echo "  pp, php-parserror                  To check PHP parsing errors"
+  echo "  xl, xdebug-log                     To check xdebug log"
+  echo "  lxp, list-xdebug-profiles          To list xdebug profiles"
   echo 'test-management:'
-	echo "  ut, unit-test                      To run php unit testing"
-	echo "  jut, javascript-unit-test          To run javascript unit testing"
-	echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
-	echo "  at, api-test                       To run api testing"
-	echo "  et, e2e-test                       To run e2e testing"
-	echo "  st, services-test                  To run services testing"
-	echo "  ft, fixtures-test                  To run fixtures testing"
-	echo "  vt, validators-test                To run validators testing"
-	echo "  ct, controllers-test               To run controllers testing"
-	echo "  ctt, common-test                   To run common testing"
+  echo "  ut, unit-test                      To run php unit testing"
+  echo "  jut, javascript-unit-test          To run javascript unit testing"
+  echo "  jrb, jut-reports-build             To build javascript unit testing reports browser user interface"
+  echo "  at, api-test                       To run api testing"
+  echo "  et, e2e-test                       To run e2e testing"
+  echo "  st, services-test                  To run services testing"
+  echo "  ft, fixtures-test                  To run fixtures testing"
+  echo "  vt, validators-test                To run validators testing"
+  echo "  ct, controllers-test               To run controllers testing"
+  echo "  ctt, common-test                   To run common testing"
   echo 'sweep-management:'
-	echo "  cs, clean-sweep                    To run the entire dev tool suite"
-	echo "  cst, clean-sweep-tests             To run only all the automated tests"
-  echo 'reset-mamagement:'
-	echo "  dr, dev-reset                      To reset OpenEMR only"
-	echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
-	echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
-	echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
+  echo "  cs, clean-sweep                    To run the entire dev tool suite"
+  echo "  cst, clean-sweep-tests             To run only all the automated tests"
+  echo 'reset-management:'
+  echo "  dr, dev-reset                      To reset OpenEMR only"
+  echo "  di, dev-install                    To install OpenEMR (reset needs to be run prior)"
+  echo "  dri, dev-reset-install             To reset and reinstall OpenEMR"
+  echo "  drid, dev-reset-install-demodata   To reset and reinstall OpenEMR with demo data"
   echo 'backup-management:'
-	echo "  bs, backup-snapshot                Create a backup snapshot"
-	echo "  rs, restore-snapshot               Restore from a snapshot"
-	echo "  ls, list-snapshots                 To list the snapshots"
-	echo "  lc, list-capsules                  List the capsules"
-	echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
-	echo "  pc, put-capsule                    Copy the capsule into the docker"
+  echo "  bs, backup-snapshot                Create a backup snapshot"
+  echo "  rs, restore-snapshot               Restore from a snapshot"
+  echo "  ls, list-snapshots                 To list the snapshots"
+  echo "  lc, list-capsules                  List the capsules"
+  echo "  gc, get-capsule                    Copy the capsule from the docker to your host directory"
+  echo "  pc, put-capsule                    Copy the capsule into the docker"
   echo 'ssl-management:'
-	echo "  fh, force-https                    Force https"
-	echo "  ufh, un-force-https                Removing forcing of https"
-	echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
-	echo "  scc, setup-client-cert             Turn on client based cert with designated package"
-	echo "  lcc, list-client-certs             To list the certificate packages"
-	echo "  pcc, put-client-cert               To copy certificate package into the docker"
-	echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
+  echo "  fh, force-https                    Force https"
+  echo "  ufh, un-force-https                Removing forcing of https"
+  echo "  ossc, on-self-signed-cert          Toggle on self signed certificates (on by default)"
+  echo "  scc, setup-client-cert             Turn on client based cert with designated package"
+  echo "  lcc, list-client-certs             To list the certificate packages"
+  echo "  pcc, put-client-cert               To copy certificate package into the docker"
+  echo "  ss, sql-ssl                        Use testing sql ssl CA cert"
   echo "  sso, sql-ssl-off                   Remove testing sql ssl CA cert"
   echo "  ssc, sql-ssl-client                Use testing sql ssl client certs"
   echo "  ssco, sql-ssl-client-off           Remove testing sql ssl client certs"
-	echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
+  echo "  css, couchdb-ssl                   Use testing couchdb ssl CA cert"
   echo "  cso, couchdb-ssl-off               Remove testing couchdb ssl CA cert"
   echo "  csc, couchdb-ssl-client            Use testing couchdb ssl client certs"
   echo "  csco, couchdb-ssl-client-off       Remove testing couchdb ssl client certs"
-	echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
+  echo "  lss, ldap-ssl                      Use testing ldap ssl CA cert"
   echo "  lso, ldap-ssl-off                  Remove testing ldap ssl CA cert"
   echo "  lsc, ldap-ssl-client               Use testing ldap ssl client certs"
   echo "  lsco, ldap-ssl-client-off          Remove testing ldap ssl client certs"
   echo 'multisite-management:'
   echo "  lm, list-multisites                List multisites"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
-	echo "  em, enable-multisite               Turn on support for multisite in setup.php"
-	echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  em, enable-multisite               Turn on support for multisite in setup.php"
+  echo "  dm, disable-multisite              Turn off support for multisite in setup.php"
   echo 'api-management:'
   echo "  bad, build-api-docs                Build and place api documentation/configuration for swagger"
   echo "  roc, register-oauth2-client        Register oauth2 client (returns client id/secret)"
   echo "  rocd, register-oauth2-client-demo  Register oauth2 client (returns client id/secret) on online demo"
   echo "  swtm, set-swagger-to-multisite     Direct swagger api testing suite to use a multisite <multisite>"
   echo 'computational-health-informatics:'
-	echo "  irp, import-random-patients        Create and import random patients <number patients>"
-	echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
+  echo "  irp, import-random-patients        Create and import random patients <number patients>"
+  echo "  gmb, generate-multisite-bank       Create bank of multisites cloned from default <number sites>"
   echo 'webroot-management:'
-	echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
-	echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
+  echo "  cwb, change-webroot-blank          Change webroot to be blank (this is default setting of environment)"
+  echo "  cwo, change-webroot-openemr        Change webroot to be openemr"
   echo 'others:'
-	echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
-	echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
-	echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
-	echo "  ec, encoding-collation             Change the database character set and collation"
-
-	exit $USAGE_EXIT_CODE
-elif [ "$FIRST_ARG" == '--version' ] || [ "$FIRST_ARG" == '-v' ]
-then
-	echo "openemr-cmd $VERSION"
-	exit $VERSION_EXIT_CODE
+  echo "  ev, ensure-version                 Upgrade OpenEMR from specified old version to current version"
+  echo "  el, enable-ldap                    Turn on support for LDAP - login credentials are admin:admin"
+  echo "  dld, disable-ldap                  Turn off support for LDAP - standard login credentials"
+  echo "  ec, encoding-collation             Change the database character set and collation"
+
+  exit "${USAGE_EXIT_CODE}"
+
+elif [[ "${FIRST_ARG}" == '--version' ]] || [[ "${FIRST_ARG}" == '-v' ]]; then
+	echo "openemr-cmd ${VERSION}"
+	exit "${VERSION_EXIT_CODE}"
 fi
 
 # Specify the docker id/name to execute the commands.
-#  default to insane dev docker, if exists
-CONTAINER_ID=$(docker ps | grep $INSANE_DEV_DOCKER | cut -f 1 -d " ")
-if [ -z $CONTAINER_ID ]
-then
-  # else, default to easy dev docker, if exists
-  CONTAINER_ID=$(docker ps | grep $EASY_DEV_DOCKER | cut -f 1 -d " ")
+# Default to insane dev docker, if exists, otherwise easy dev docker.
+# Try to find the insane dev docker ID directly
+if insane_id=$(docker ps --filter "name=${INSANE_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${insane_id}" ]]; then
+  CONTAINER_ID="${insane_id}"
+# Try to find the easy dev docker ID directly
+elif easy_id=$(docker ps --filter "name=${EASY_DEV_DOCKER}" --format "{{.ID}}" | head -n 1); [[ -n "${easy_id}" ]]; then
+  CONTAINER_ID="${easy_id}"
+else
+  # Neither container found running, set CONTAINER_ID to empty.
+  # The script's later logic handles the -d flag or errors if no container is specified.
+  CONTAINER_ID=""
 fi
+
 # override the default container setting if supplied via the -d parameter
 #  (also removing no longer needed parameters via shift)
 CHANGE_CONTAINER_CODE=25
-if [ "$FIRST_ARG" == '-d' ] && [ $# -ge 3 ]
-then
-	CONTAINER_ID=$2
-	FIRST_ARG=$3
+if [[ "${FIRST_ARG}" == '-d' ]] && [[ $# -ge 3 ]]; then
+	CONTAINER_ID="$2"
+	FIRST_ARG="$3"
 	shift 3
-elif [ "$FIRST_ARG" == '-d' ] && [ $# -lt 3 ]
-then
+elif [[ "${FIRST_ARG}" == '-d' ]] && [[ $# -lt 3 ]]; then
 	echo 'Please provide a docker id/name when using -d parameter.'
 	echo 'e.g. openemr-cmd -d docker_openemr-7-3-redis-312_1 dl'
-	exit $CHANGE_CONTAINER_CODE
+	exit "${CHANGE_CONTAINER_CODE}"
 else
   shift
 fi
path: utilities/openemr-cmd/openemr-cmd
user: login: msummers42
body: Can you retry this suggestion, it is giving me an error "Applying suggestions on deleted lines is currently not supported. "

created_at: 2025-04-24T18:30:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -294,15 +347,16 @@ FINAL_EXIT_CODE=0
 
 # Confirm the docker install or not.
 DOCKER_CODE=16
-which docker &>/dev/null
-[ $? -ne 0 ] && echo "Please check docker install or not." && exit $DOCKER_CODE
+if ! command -v docker &>/dev/null; then
+  echo "Please check docker install or not."
+  exit "${DOCKER_CODE}"
+fi
 
 # Script usage.
-if [ $# -eq 0 ] || [ "$FIRST_ARG" == '--help' ] || [ "$FIRST_ARG" == '-h' ]
-then
+if [[ $# -eq 0 || "${FIRST_ARG}" = '--help' || "${FIRST_ARG}" = '-h' ]]; then
   echo ""
-  echo "Usage: `basename $0` COMMAND [ARGS]"
-  echo "Usage: `basename $0` -d <docker name> COMMAND [ARGS]"
+  echo "Usage: $(basename "$0") COMMAND [ARGS]"
+  echo "Usage: $(basename "$0") -d <docker name> COMMAND [ARGS]"
path: utilities/openemr-cmd/openemr-cmd
user: login: kojiromike
body: ```suggestion
  echo "Usage: ${0##*/} COMMAND [ARGS]"
  echo "Usage: ${0##*/} -d <docker name> COMMAND [ARGS]"
```

…to avoid the subshell and avoid doing it twice :)
created_at: 2025-04-24T18:47:32Z
author_association: MEMBER
diff_hunk: @@ -294,15 +347,16 @@ FINAL_EXIT_CODE=0
 
 # Confirm the docker install or not.
 DOCKER_CODE=16
-which docker &>/dev/null
-[ $? -ne 0 ] && echo "Please check docker install or not." && exit $DOCKER_CODE
+if ! command -v docker &>/dev/null; then
+  echo "Please check docker install or not."
+  exit "${DOCKER_CODE}"
+fi
 
 # Script usage.
-if [ $# -eq 0 ] || [ "$FIRST_ARG" == '--help' ] || [ "$FIRST_ARG" == '-h' ]
-then
+if [[ $# -eq 0 || "${FIRST_ARG}" = '--help' || "${FIRST_ARG}" = '-h' ]]; then
   echo ""
-  echo "Usage: `basename $0` COMMAND [ARGS]"
-  echo "Usage: `basename $0` -d <docker name> COMMAND [ARGS]"
+  echo "Usage: $(basename "$0") COMMAND [ARGS]"
+  echo "Usage: $(basename "$0") -d <docker name> COMMAND [ARGS]"
path: utilities/openemr-cmd/openemr-cmd
user: login: msummers42
body: I tend to forget about this way to grab the basename, nice.
created_at: 2025-04-24T19:40:48Z
author_association: CONTRIBUTOR

PR comments:
user: login: msummers42
created_at: 2025-04-24T16:26:00Z
body: @bradymiller Hello! I wrote this changeset hoping to start a conversation about some of the styles/conventions used in the bash scripts throughout the project. I would really appreciate your thoughts and any feedback on what is proposed here. Cheers!
author_association: CONTRIBUTOR
user: login: jesdynf
created_at: 2025-04-25T02:39:17Z
body: I'll look this over no later than Saturday.
author_association: COLLABORATOR
user: login: jesdynf
created_at: 2025-04-26T23:13:29Z
body: @bradymiller I've sight-read this and it all looks good, but I haven't tested it and I don't do anything that *would* test it, nor am I certain I understand who does use these, and where they do so, so I'm not this-minute willing to pull it in. Do you think it's probably fine and a problem would just break developer environments until they yell loud enough for us to fix it?
author_association: COLLABORATOR
user: login: bradymiller
created_at: 2025-04-28T08:12:50Z
body: hi @jesdynf @msummers42 , I'll do road testing on this on Tuesday. If goes well (which I am guessing it well), will then bring this in.
author_association: MEMBER
user: login: bradymiller
created_at: 2025-04-30T09:28:39Z
body: Sanity testing well on both easy and insane dev environments. Bringing in. Thanks for the improvements @msummers42 ! and thanks for the reviews @kojiromike and @jesdynf !
Especially like the new support for `docker compose` and continued compatibility with `docker-compose` !
author_association: MEMBER