diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 61d44aef2be3abfb942a97dd22fc599574ff7a31..78a2b161680ddaf01c1bb349c658b7afcd6e2b9f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -52,6 +52,24 @@ sphinx-documentation:
       # Run sphinx-build (treating warnings as errors)
       sphinx-build -W docs/source output
 
+conda-test:
+  stage: test
+  script:
+    - |
+      # Install system dependencies
+      apt-get install --yes --no-install-recommends git bzip2
+
+      # Install micromamba
+      curl -Ls https://micromamba.snakepit.net/api/micromamba/linux-64/1.4.2 | tar xvj bin/micromamba
+      chmod +x ./bin/micromamba
+      export MAMBA_ROOT_PREFIX=/opt/micromamba
+      ./bin/micromamba shell --yes init ${MAMBA_ROOT_PREFIX}
+      source /root/.bashrc
+
+      # Test creation conda environment
+      micromamba env create --dry-run --name pantools --yes --strict-channel-priority \
+        --channel conda-forge --channel bioconda --file conda.yaml
+
 unit-tests:
   stage: test
   script:
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 6bf3f50232dedfee51dca4cc5c4855fdc39df909..922a84ed94a2980f4c2d49272866ed82d2b50f58 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -3,12 +3,19 @@ repos:
     hooks:
     - id: pre-commit-validate-config
       name: Validate pre-commit config
-      description: 'Validates the .pre-commit-config.yaml file'
+      description: 'Validates the .pre-commit-config.yaml file.'
       files: '.pre-commit-config.yaml'
       entry: pre-commit-validate-config
       args:
         - .pre-commit-config.yaml
       language: system
+    - id: conda-yaml-validate
+      name: Validate conda YAML
+      description: 'Validates conda.yaml for creation of conda environment.'
+      files: 'conda.yaml'
+      entry: mamba
+      args: [env, create, -d, -n=test_pantools, -f=conda.yaml]
+      language: system
     - id: maven-compile
       name: Compile with Maven
       description: 'Compile all code with mvn compile.'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d9f3ff4eebe8bb2b32c732fa4f7f8ea0bbb7a223..75f1ca8e51baee1103e93b9a44159e5393991ac1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,8 @@ All notable changes to Pantools will be documented in this file.
 ### Changed
 - `pantools busco_protein`, `pantools gene_classification`, `pantools kmer_classification`, `pantools group_info`, `pantools rename_phylogeny`, `pantools create_tree_template`, `pantools core_phylogeny`, `pantools rename_matrix` to be compatible with possible added phasing information in a pangenome database (!148).
 - `busco_protein` is no longer functional with BUSCO v3 and odb9 datasets (!146).
+- `conda_linux.yaml` and `conda_macos.yaml` now unified in one `conda.yaml` file (!203).
+- Updated KMC version to >=3.1.0 (!203).
 
 ### Fixed
 - `pantools core_phylogeny` and `pantools consensus_tree` now ignore MSAs that could not be trimmed (!197).
diff --git a/README.md b/README.md
index 787780a78aa19ca38271e3b5315e26b5372d295c..d77b489a53e7d7ed48fb8100ccd4ea77873021f7 100755
--- a/README.md
+++ b/README.md
@@ -50,8 +50,7 @@ git checkout v4.0.0
 
 We provide conda environments for installing all dependencies of PanTools, which can be installed using conda/mamba (we recommend using mamba):
 ```bash
-mamba env create -n pantools -f conda_linux.yaml # for linux
-mamba env create -n pantools -f conda_macos.yaml # for macOS (does not include busco)
+mamba env create -n pantools -f conda.yaml
 ```
 
 ## Building a runnable jar
diff --git a/conda_linux.yaml b/conda.yaml
similarity index 88%
rename from conda_linux.yaml
rename to conda.yaml
index 8da2a955552c26419019b4dea77f16eddea8c13f..4e05083448468104a08392a1a8a40b2a48d689b7 100644
--- a/conda_linux.yaml
+++ b/conda.yaml
@@ -4,8 +4,7 @@ channels:
 dependencies:
   - openjdk=8.0
   - maven
-  - python=3.7
-  - kmc=3.0.1
+  - kmc>=3.1.0
   - mcl
   - mafft
   - iqtree
@@ -13,7 +12,7 @@ dependencies:
   - mash=2.3
   - fastani
   - busco=5
-  - r-base
+  - r-base>=3.5
   - r-ggplot2
   - r-ape
   - graphviz
diff --git a/conda_macos.yaml b/conda_macos.yaml
deleted file mode 100644
index 6225cc6c281867e19859e2abb192ca23a03039bf..0000000000000000000000000000000000000000
--- a/conda_macos.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-channels:
-  - conda-forge
-  - bioconda
-dependencies:
-  - openjdk=8.0
-  - maven
-  - python=3.7
-  - kmc=3.0.1
-  - mcl
-  - mafft
-  - iqtree
-  - fasttree
-  - mash=2.3
-  - fastani
-    #- busco=5 #causes conflicts
-  - r-base
-  - r-ggplot2
-  - r-ape
-  - graphviz
-  - aster=1.3
-    #- bcftools>=1.12 #can only be installed from this YAML without strict channel priority
-  - tabix
-  - blast
-  - pal2nal>=14.1
-  - paml>=4.10.6
-    #- r-cowplot>=1.1.1 #causes conflicts
diff --git a/docs/source/developer_guide/install.rst b/docs/source/developer_guide/install.rst
index 2025d2a1b9994cf8fce8fb478c968b81857e120f..dc22dbef581c614105281141a1a475474bf331f8 100644
--- a/docs/source/developer_guide/install.rst
+++ b/docs/source/developer_guide/install.rst
@@ -27,19 +27,16 @@ below.
 Install dependencies using Conda
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-To install all dependencies into a separate environment, run the
-following commands. Please choose the conda_linux.yaml or
-conda_macos.yaml file depending on your operating system. These files
-be found in the `release <https://git.wur.nl/bioinformatics/pantools/-/
-releases>`_ or in the PanTools home when working with the git itself. There is a
-difference between the two files because not all tools are available for macOS.
-For smooth dependency resolving with conda, it is recommended to use strict
-channel priority and to only use the bioconda and conda-forge channels.
+To install all dependencies into a separate environment, run the following
+commands. Please use the conda.yaml file which can be found in the
+`release <https://git.wur.nl/bioinformatics/pantools/-/releases>`_ or in the
+PanTools home when working with the git itself. For smooth dependency resolving
+with conda, it is recommended to use strict channel priority and to only use the
+bioconda and conda-forge channels.
 
 .. code:: bash
 
-   $ mamba env create -n pantools -f conda_linux.yaml #for Linux
-   $ mamba env create -n pantools -f conda_macos.yaml #for macOS
+   $ mamba env create -n pantools -f conda.yaml
 
 --------------
 
diff --git a/docs/source/developer_guide/release.rst b/docs/source/developer_guide/release.rst
index f5875ce5a8053b9469bc2c5097ed32d904cfbd31..dccaf5d4cc02ea71f92d5f0eab5a5b52a262fcdc 100644
--- a/docs/source/developer_guide/release.rst
+++ b/docs/source/developer_guide/release.rst
@@ -16,6 +16,6 @@ The following steps are required to create a new release of PanTools:
    and delete the **new release branch**.
 9. Put a tag on the merge commit in the **current stable release branch**.
 10. Locally compile PanTools and put the compiled JAR file on the server.
-11. Create a release from the tag and attach 1) the compiled JAR file, 2) the
-    ``conda_linux.yaml`` file, and 3) the ``conda_macos.yaml`` file.
+11. Create a release from the tag and attach 1) the compiled JAR file, and 2)
+    the ``conda.yaml`` file.
 12. Update the bioconda recipe for the new release.
diff --git a/docs/source/user_guide/install.rst b/docs/source/user_guide/install.rst
index c88de86ec8128077646e5230dbdce22741ed2a78..0a7f37345b44057884f6af8284c83b6ed6e40b59 100644
--- a/docs/source/user_guide/install.rst
+++ b/docs/source/user_guide/install.rst
@@ -20,8 +20,8 @@ For users that don't have conda installed, we recommend to install conda first:
 
 .. substitution-code-block:: bash
 
-   $ wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
-   $ bash Miniconda3-latest-Linux-x86_64.sh
+   $ curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"
+   $ bash Miniforge3-$(uname)-$(uname -m).sh
 
    # Follow the instructions on the screen
    # Restart your terminal
@@ -34,23 +34,13 @@ For users that don't have conda installed, we recommend to install conda first:
 
    # Restart your terminal
 
-Next, we recommend to install mamba into the conda base environment to enable
-much faster dependency solving:
-
-.. substitution-code-block:: bash
-
-   $ conda install -n base mamba
-
-Finally, we can install PanTools. We recommend to install PanTools into a
+Now, we can install PanTools. We recommend to install PanTools into a
 separate environment. Please make sure you install the most recent versions of
 the tools.
-NB: not all dependencies are available for macOS, therefore please use the
-correct line from this code block depending on your operating system:
 
 .. substitution-code-block:: bash
 
-   $ mamba create -n pantools pantools bcftools busco  # Linux
-   $ mamba create -n pantools pantools  # macOS
+   $ mamba create -n pantools pantools
 
 Please make sure to activate the environment before using PanTools:
 
@@ -77,19 +67,15 @@ environment that has all dependencies.
 Install dependencies using conda
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-Please choose the conda_linux.yaml or conda_macos.yaml file depending on your
-operating system. These files be found on the
-`release page <https://git.wur.nl/bioinformatics/pantools/-/releases>`_. The
-difference between the two files comes from some dependencies conflicting on
-macOS but not on Linux. Only on Linux a full installation of PanTools is
-possible. On macOS, some functionalities will not be available.
+All dependencies are listed in conda.yaml which can be found on the
+`release page <https://git.wur.nl/bioinformatics/pantools/-/releases>`_.
 
 For users that don't have conda installed, we recommend to install conda first:
 
 .. substitution-code-block:: bash
 
-   $ wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
-   $ bash Miniconda3-latest-Linux-x86_64.sh
+   $ curl -L -O "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh"
+   $ bash Miniforge3-$(uname)-$(uname -m).sh
 
    # Follow the instructions on the screen
    # Restart your terminal
@@ -102,19 +88,11 @@ For users that don't have conda installed, we recommend to install conda first:
 
    # Restart your terminal
 
-Next, we recommend to install mamba into the conda base environment to enable
-much faster dependency solving:
-
-.. substitution-code-block:: bash
-
-   $ conda install mamba -n base -c conda-forge
-
-Finally, we can install all dependencies into a separate environment:
+Now, we can install all dependencies into a separate environment:
 
 .. substitution-code-block:: bash
 
-   $ mamba env create -n pantools -f conda_linux.yaml #for Linux
-   $ mamba env create -n pantools -f conda_macos.yaml #for macOS
+   $ mamba env create -n pantools -f conda.yaml
 
 Please make sure to activate the environment before using PanTools:
 
diff --git a/src/main/java/nl/wur/bif/pantools/construction/index/IndexDatabase.java b/src/main/java/nl/wur/bif/pantools/construction/index/IndexDatabase.java
index b92287659e08f111b4d766a026a7d28d30e26338..4043a4fad2969e06818ec0f3222976762da8a177 100755
--- a/src/main/java/nl/wur/bif/pantools/construction/index/IndexDatabase.java
+++ b/src/main/java/nl/wur/bif/pantools/construction/index/IndexDatabase.java
@@ -16,7 +16,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import static nl.wur.bif.pantools.utils.Globals.*;
-import static nl.wur.bif.pantools.utils.Utils.executeCommand;
+import static nl.wur.bif.pantools.utils.Utils.runCommandWithOutput;
 
 /**
  * Implements all the functionality to build a KMC-based kmer index. 
@@ -179,7 +179,7 @@ public final class IndexDatabase {
     public IndexDatabase(String index_path, String genomes_path_file, SequenceDatabase genomeDb, int k) {
         int i, j, number_of_pages, record_size, page_size, full_page_size;
         long number_of_prefixes, longest_scaffold = 0;
-        Pantools.logger.info("Creating index in {}", index_path);
+        Pantools.logger.debug("Creating index in {}", index_path);
         try {
             Files.createDirectory(Paths.get(index_path));
             Run_KMC(index_path, genomes_path_file, genomeDb, k);
@@ -212,7 +212,7 @@ public final class IndexDatabase {
             offset_len = (int)Math.round(Math.ceil( Math.log(longest_scaffold) / Math.log(2) / 8));
             poniter_length = 2 * id_len + offset_len + 1;
             write_info(index_path, "sorted");
-            Pantools.logger.info("Indexing kmers...");
+            Pantools.logger.debug("Indexing kmers...");
         // load the prefix file into the memory    
             Pantools.logger.trace("Loading prefixes in memory...");
             number_of_prefixes = 1 << (2 * pre_len);
@@ -283,21 +283,31 @@ public final class IndexDatabase {
         // move current index files to directory old_darabase
        
         try{
-        // make new index for new genomes
+            // make new index for new genomes
             Pantools.logger.info("Running KMC with K = {} ...", old_database.K);
-            executeCommand(KMC + " -cs127 -r -k" + old_database.K + " -t" + THREADS + " -ci1 -fm " + (genomeDb.num_genomes - previous_num_genomes > 1 ? "@" +
+            final String index_command = KMC + " -cs127 -r -k" + old_database.K + " -t" + THREADS + " -ci1 -fm " + (genomeDb.num_genomes - previous_num_genomes > 1 ? "@" +
                     genomes_path_file.trim() : genomeDb.genome_names[previous_num_genomes + 1]) +
-                    " " + index_path + "new " + index_path); 
-           
-               
-            
-        // merge two indeces    
-            executeCommand(KMC + "_tools union " + index_path + "sorted " + index_path + "new " + index_path + "merged");
+                    " " + index_path + "new " + index_path;
+            Pantools.logger.debug("KMC command: {}", index_command);
+
+            final String index_output = runCommandWithOutput(index_command);
+            Pantools.logger.trace("KMC output: {}", index_output);
+
+            // merge two indices
+            Pantools.logger.debug("Merging two indices.");
+
+            final String merge_command = KMC + "_tools simple union " + index_path + "sorted " + index_path + "new " + index_path + "merged";
+            Pantools.logger.debug("KMC command: {}", merge_command);
+
+            final String merge_output = runCommandWithOutput(merge_command);
+            Pantools.logger.trace("KMC output: {}", merge_output);
+
             pre_file = new RandomAccessFile(index_path + "merged" + PREFIX_FILE_EXTENTION, "r");
             pre_file.seek(pre_file.length() - 8);
             header_pos = read_int(pre_file);
             pre_file.seek(pre_file.length() - 8 - header_pos);
-        // read the merged index properties    
+
+            // read the merged index properties
             K = read_int(pre_file);
             mode = read_int(pre_file);
             ctr_size = read_int(pre_file);
@@ -314,10 +324,11 @@ public final class IndexDatabase {
             offset_len = (int)Math.round(Math.ceil( Math.log(longest_scaffold) / Math.log(2) / 8));
             poniter_length = 2 * id_len + offset_len + 1;
             write_info(index_path, "merged");
-            Pantools.logger.info("number of available kmers:\t{}", old_database.kmers_num);
-            Pantools.logger.info("number of new kmers:\t{}", (kmers_num - old_database.kmers_num));
+            Pantools.logger.info("Number of available kmers:\t{}", old_database.kmers_num);
+            Pantools.logger.info("Number of new kmers:\t{}", (kmers_num - old_database.kmers_num));
             Pantools.logger.info("Total number of kmers:\t{}", kmers_num);
-        // load the prefix file into the memory
+
+            // load the prefix file into the memory
             Pantools.logger.trace("loading new prefixes in memory...");
             number_of_prefixes = 1 << (2 * pre_len);
             prefix_ptr = new long[(int)number_of_prefixes];
@@ -335,7 +346,8 @@ public final class IndexDatabase {
             }
             pre_buff = null;
             pre_file.close();
-        // mapping suffix file into the memory
+
+            // mapping suffix file into the memory
             Pantools.logger.trace("Mapping new suffix file to memory...");
             record_size = ctr_size + suf_len / 4;
             full_page_size = MAX_BYTE_COUNT / record_size * record_size; // in bytes
@@ -422,60 +434,46 @@ public final class IndexDatabase {
      */
     public void Run_KMC(String index_path, String genomes_path_file, SequenceDatabase genomeDb, int k) {
         double p = 0;
-        String output;
         try{
         Runtime.getRuntime().exec(KMC); // to check if kmc is reachable
         if (k > -1) { // K is not given by the user, then calculate the optimal K
+            Pantools.logger.info("K is given by the user: {}", k);
+
             K = k;
             if (K % 2 == 0) // Even values are problamatic to localization process 
                 K += 1;
-            
-            String kmc_command = KMC + " -cs127 -k" + K + " -t" + THREADS + " -ci1 -fm " +
+
+            final String kmc_command = KMC + " -cs127 -k" + K + " -t" + THREADS + " -ci1 -fm " +
                     (genomeDb.num_genomes > 1 ? "@" + genomes_path_file.trim() : genomeDb.genome_names[1]) + " " + index_path + "/kmers " + index_path;
             Pantools.logger.debug("KMC command: {}", kmc_command);
-            executeCommand(kmc_command);
-            if (new File(index_path + "/kmers.kmc_pre").exists() && new File(index_path + "/kmers.kmc_suf").exists()) {
-                final String kmcSortCommand = String.format(
-                        "kmc_tools -t%1$d sort %2$s/kmers %2$s/sorted",
-                        THREADS,
-                        index_path);
-                output = executeCommand(kmcSortCommand);
-            // Small databases are usually sorted already    
-                if (output.startsWith("This database contains sorted k-mers already!")) {
-                    new File(index_path + "/kmers.kmc_pre").renameTo(new File(index_path + "/sorted.kmc_pre"));
-                    new File(index_path + "/kmers.kmc_suf").renameTo(new File(index_path + "/sorted.kmc_suf"));
-                } else {
-                    new File(index_path + "/kmers.kmc_pre").delete();
-                    new File(index_path + "/kmers.kmc_suf").delete();
-                }            
+            final String output = runCommandWithOutput(kmc_command);
+            Pantools.logger.trace("KMC output: {}", output);
+
+            if (checkIfKmcIndexExists(index_path)) {
+                sortKmcIndex(index_path);
             } else {
                 Pantools.logger.error("No kmc index found in {}", index_path);
-                System.exit(1);
+                throw new RuntimeException("Missing kmc index");
             }
         } else {
+            Pantools.logger.info("K is not given by the user. Calculating the optimal K.");
+
             K = Math.round((float)(Math.log(genomeDb.number_of_bytes * 200)/Math.log(4)));
             K += (K % 2 == 0 ? 1 : 0);
             do {
                 K -= 2;
-            Pantools.logger.info("K = {}", K);
-            String kmc_command = KMC + " -cs127 -k" + K + " -t" + THREADS + " -ci1 -fm " +
+                Pantools.logger.debug("K = {}", K);
+
+                final String kmc_command = KMC + " -cs127 -k" + K + " -t" + THREADS + " -ci1 -fm " +
                         (genomeDb.num_genomes > 1 ? "@" + genomes_path_file.trim() : genomeDb.genome_names[1]) + " " + index_path + "/kmers " + index_path;
                 Pantools.logger.debug("KMC command: {}", kmc_command);
-                executeCommand(kmc_command);
-                if (new File(index_path + "/kmers.kmc_pre").exists() && new File(index_path + "/kmers.kmc_suf").exists()) {
-                    final String kmcSortCommand = String.format(
-                            "kmc_tools -t%1$d sort %2$s/kmers %2$s/sorted",
-                            THREADS,
-                            index_path);
-                    output = executeCommand(kmcSortCommand);
-                // Small databases are usually sorted already    
-                    if (output.startsWith("This database contains sorted k-mers already!")) {
-                        new File(index_path + "/kmers.kmc_pre").renameTo(new File(index_path + "/sorted.kmc_pre"));
-                        new File(index_path + "/kmers.kmc_suf").renameTo(new File(index_path + "/sorted.kmc_suf"));
-                    } else {
-                        new File(index_path + "/kmers.kmc_pre").delete();
-                        new File(index_path + "/kmers.kmc_suf").delete();
-                    }            
+
+                final String kmc_output = runCommandWithOutput(kmc_command);
+                Pantools.logger.trace("KMC output: {}", kmc_output);
+
+                if (checkIfKmcIndexExists(index_path)) {
+                    sortKmcIndex(index_path);
+
                     pre_file = new RandomAccessFile(index_path + "/sorted.kmc_pre", "r");
                     pre_file.seek(pre_file.length() - 8);
                     header_pos = read_int(pre_file);
@@ -499,37 +497,66 @@ public final class IndexDatabase {
                     pre_file.close();
                 } else {
                     Pantools.logger.error("No kmc index found in {}", index_path);
-                    System.exit(1);
+                    throw new RuntimeException("Missing kmc index");
                 }
             } while (p < 0.01);
             K += 2;
-            executeCommand(KMC + " -cs127 -k" + K + " -t" + THREADS + " -ci1 -fm " +
-                    (genomeDb.num_genomes > 1 ? "@" + genomes_path_file.trim() : genomeDb.genome_names[1]) + " " + index_path + "/kmers " + index_path);
-            if (new File(index_path + "/kmers.kmc_pre").exists() && new File(index_path + "/kmers.kmc_suf").exists()) {
-                final String kmcSortCommand = String.format(
-                        "kmc_tools -t%1$d sort %2$s/kmers %2$s/sorted",
-                        THREADS,
-                        index_path);
-                output = executeCommand(kmcSortCommand);
-            // Small databases are usually sorted already    
-                if (output.startsWith("This database contains sorted k-mers already!")) {
-                    new File(index_path + "/kmers.kmc_pre").renameTo(new File(index_path + "/sorted.kmc_pre"));
-                    new File(index_path + "/kmers.kmc_suf").renameTo(new File(index_path + "/sorted.kmc_suf"));
-                } else {
-                    new File(index_path + "/kmers.kmc_pre").delete();
-                    new File(index_path + "/kmers.kmc_suf").delete();
-                } 
+
+            final String kmc_command = KMC + " -cs127 -k" + K + " -t" + THREADS + " -ci1 -fm " +
+                    (genomeDb.num_genomes > 1 ? "@" + genomes_path_file.trim() : genomeDb.genome_names[1]) + " " + index_path + "/kmers " + index_path;
+            Pantools.logger.debug("KMC command: {}", kmc_command);
+
+            final String kmc_output = runCommandWithOutput(kmc_command);
+            Pantools.logger.trace("KMC output: {}", kmc_output);
+
+            if (checkIfKmcIndexExists(index_path)) {
+                sortKmcIndex(index_path);
             } else {
                 Pantools.logger.error("No kmc index found in {}", index_path);
-                System.exit(1);
+                throw new RuntimeException("Missing kmc index");
             }
         }
-        Pantools.logger.info("K = {}", K);
+        Pantools.logger.debug("K = {}", K);
         } catch (IOException ex) {
             Pantools.logger.warn("Failed to find K!");
         }
     }
 
+    /**
+     * Checks if the KMC index exists in the given path
+     * @param index_path Path to the index database
+     * @return True if the KMC index exists, false otherwise
+     */
+    private boolean checkIfKmcIndexExists(String index_path) {
+        Pantools.logger.debug("Checking if kmc index exists in {}", index_path);
+        boolean indexExists = new File(index_path + "/kmers.kmc_pre").exists() && new File(index_path + "/kmers.kmc_suf").exists();
+        Pantools.logger.trace("KMC index exists: {}", indexExists);
+        return indexExists;
+    }
+
+    /**
+     * Sorts the KMC index in the given path
+     * @param index_path Path to the index database
+     */
+    private void sortKmcIndex(String index_path) {
+        Pantools.logger.debug("Sorting kmc index in {}", index_path);
+
+        final String command = KMC + "_tools transform " + index_path + "/kmers sort " + index_path + "/sorted";
+        Pantools.logger.debug("KMC command: {}", command);
+
+        final String output = runCommandWithOutput(command);
+        Pantools.logger.trace("KMC output: {}", output);
+
+        // Small databases are usually sorted already
+        if (output.startsWith("Warning: input database is already sorted.")) {
+            new File(index_path + "/kmers.kmc_pre").renameTo(new File(index_path + "/sorted.kmc_pre"));
+            new File(index_path + "/kmers.kmc_suf").renameTo(new File(index_path + "/sorted.kmc_suf"));
+        } else {
+            new File(index_path + "/kmers.kmc_pre").delete();
+            new File(index_path + "/kmers.kmc_suf").delete();
+        }
+    }
+
     /**
      * Writes the index database specification in the info file of the index database
      * 
diff --git a/src/main/java/nl/wur/bif/pantools/utils/Utils.java b/src/main/java/nl/wur/bif/pantools/utils/Utils.java
index 502569e8b70dbe621c98a9d39ed7be1937297844..aab4ca5681677b19f743799893b628a3d530a56e 100644
--- a/src/main/java/nl/wur/bif/pantools/utils/Utils.java
+++ b/src/main/java/nl/wur/bif/pantools/utils/Utils.java
@@ -540,25 +540,29 @@ public final class Utils {
 
     /**
      * Executes a shell command.
-     *
-     * @param command The command
-     * @return The output of the bash command
-     */
-    public static String executeCommand(String command) {
-        StringBuilder exe_output = new StringBuilder();
-        String line = "";
-        Process p;
+     * @param command the shell command
+     * @return the output (both stdout and stderr) of the command
+     */
+    public static String runCommandWithOutput(String command) {
+        List<String> cmd = new ArrayList<>();
+        cmd.add("sh");
+        cmd.add("-c");
+        cmd.add(command);
+        ProcessBuilder pb = new ProcessBuilder(cmd);
         try {
-            p = Runtime.getRuntime().exec(command);
+            Process p = pb.start();
             p.waitFor();
             BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
+            StringBuilder output = new StringBuilder();
+            String line;
             while ((line = reader.readLine()) != null) {
-                exe_output.append(line).append("\n");
+                output.append(line).append("\n");
             }
-        } catch (Exception e) {
+            return output.toString();
+        } catch (IOException | InterruptedException e) {
             e.printStackTrace();
+            throw new RuntimeException(e.getMessage());
         }
-        return exe_output.toString();
     }
 
     /**