func (t *Task) tempDirsExist() bool {
	if _, err := os.Stat(t.TempDir()); os.IsNotExist(err) {
		return false
	}
	return true
}
------------------------------------------------------------------------
Helper methods for the Execute method
------------------------------------------------------------------------
anyTempFileExists checks if any temporary workflow files exist and if so, returns true
package scipipe
import (
	"crypto/sha1"
	"encoding/hex"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
)
type Task struct {
	Name          string
	Command       string
	CustomExecute func(*Task)
	InIPs         map[string]*FileIP
	OutIPs        map[string]*FileIP
	Params        map[string]string
	Tags          map[string]string
	Done          chan int
	cores         int
	workflow      *Workflow
	Process       *Process
	portInfos     map[string]*PortInfo
	subStreamIPs  map[string][]*FileIP
}
func NewTask(workflow *Workflow, process *Process, name string, cmdPat string, inIPs map[string]*FileIP, outPathFuncs map[string]func(*Task) string, portInfos map[string]*PortInfo, params map[string]string, tags map[string]string, prepend string, customExecute func(*Task), cores int) *Task {
	t := &Task{
		Name:          name,
		InIPs:         inIPs,
		OutIPs:        make(map[string]*FileIP),
		Params:        params,
		Tags:          tags,
		Command:       "",
		CustomExecute: customExecute,
		Done:          make(chan int),
		cores:         cores,
		workflow:      workflow,
		Process:       process,
		portInfos:     portInfos,
		subStreamIPs:  make(map[string][]*FileIP),
	}
	for ptName, ptInfo := range portInfos {
		if ptInfo.join && ptInfo.joinSep != "" {
			ips := []*FileIP{}
			for ip := range inIPs[ptName].SubStream.Chan {
				ips = append(ips, ip)
			}
			t.subStreamIPs[ptName] = ips
		}
	}
	for oname, outPathFunc := range outPathFuncs {
		oip, err := NewFileIP(outPathFunc(t))
		if err != nil {
			process.Failf("Could not create out IP %s: %v", oname, err)
		}
		if ptInfo, ok := portInfos[oname]; ok {
			if ptInfo.doStream {
				oip.doStream = true
			}
		}
		t.OutIPs[oname] = oip
	}
	t.Command = t.formatCommand(cmdPat, portInfos, inIPs, t.subStreamIPs, t.OutIPs, params, tags, prepend)
	return t
}
const (
	parentDirPlaceHolder = "__parent__"
)
func (t *Task) formatCommand(cmd string, portInfos map[string]*PortInfo, inIPs map[string]*FileIP, subStreamIPs map[string][]*FileIP, outIPs map[string]*FileIP, params map[string]string, tags map[string]string, prepend string) string {
	r := getShellCommandPlaceHolderRegex()
	placeHolderMatches := r.FindAllStringSubmatch(cmd, -1)
	type placeHolderInfo struct {
		match     string
		portName  string
		modifiers []string
	}
	placeHolderInfos := make([]*placeHolderInfo, 0)
	for _, match := range placeHolderMatches {
		restMatch := match[2]
		parts := strings.Split(restMatch, "|")
		portName := parts[0]
		modifiers := parts[1:]
		placeHolderInfos = append(placeHolderInfos,
			&placeHolderInfo{
				portName:  portName,
				match:     match[0],
				modifiers: modifiers,
			})
	}
	for _, placeHolder := range placeHolderInfos {
		portName := placeHolder.portName
		portInfo := portInfos[portName]
		var replacement string
		switch portInfo.portType {
		case "o":
			if outIPs[portName] == nil {
				t.Failf("Missing outpath for outport (%s) for command (%s)", portName, cmd)
			}
			replacement = outIPs[portName].TempPath()
			replacement = applyPathModifiers(replacement, placeHolder.modifiers)
			replacement = replaceParentDirsWithPlaceholder(replacement)
		case "os":
			if outIPs[portName] == nil {
				t.Failf("Missing outpath for outport (%s) for command (%s)", portName, cmd)
			}
			replacement = outIPs[portName].FifoPath()
			replacement = applyPathModifiers(replacement, placeHolder.modifiers)
			if !strInSlice("basename", placeHolder.modifiers) {
				replacement = prependParentDirPath(replacement)
			}
		case "i":
			if inIPs[portName] == nil {
				t.Failf("Missing in-IP for inport (%s) for command (%s)", portName, cmd)
			}
			if portInfo.join && portInfo.joinSep != "" {
				paths := []string{}
				for _, ip := range subStreamIPs[portName] {
					path := ip.Path()
					path = applyPathModifiers(path, placeHolder.modifiers)
					path = prependParentDirPath(path)
					paths = append(paths, path)
				}
				replacement = strings.Join(paths, portInfo.joinSep)
			} else {
				if inIPs[portName].Path() == "" {
					t.Failf("Missing inpath for inport (%s), and no substream, for command (%s)", portName, cmd)
				}
				if inIPs[portName].doStream {
					replacement = inIPs[portName].FifoPath()
				} else {
					replacement = inIPs[portName].Path()
				}
				replacement = applyPathModifiers(replacement, placeHolder.modifiers)
				if !strInSlice("basename", placeHolder.modifiers) {
					replacement = prependParentDirPath(replacement)
				}
			}
		case "p":
			if params[portName] == "" {
				t.Failf("Missing param value for param (%s) for command (%s)", portName, cmd)
			} else {
				replacement = params[portName]
				replacement = applyPathModifiers(replacement, placeHolder.modifiers)
			}
		case "t":
			if tags[portName] == "" {
				t.Failf("Missing tag value for tag (%s) for command (%s)", portName, cmd)
			} else {
				replacement = tags[portName]
				replacement = applyPathModifiers(replacement, placeHolder.modifiers)
			}
		default:
			t.Failf("Replace failed for port (%s) for command (%s)", portName, cmd)
		}
		cmd = strings.Replace(cmd, placeHolder.match, replacement, -1)
	}
	if prepend != "" {
		cmd = fmt.Sprintf("%s %s", prepend, cmd)
	}
	return cmd
}
func (t *Task) InIP(portName string) *FileIP {
	if t.InIPs[portName] == nil {
		t.Failf("No such in-portname (%s)", portName)
	}
	return t.InIPs[portName]
}
func (t *Task) InPath(portName string) string {
	return t.InIP(portName).Path()
}
func (t *Task) OutIP(portName string) *FileIP {
	if ip, ok := t.OutIPs[portName]; ok {
		return ip
	}
	t.Failf("No such out-portname (%s)", portName)
	return nil
}
func (t *Task) OutPath(portName string) string {
	return t.OutIP(portName).Path()
}
func (t *Task) Param(portName string) string {
	if param, ok := t.Params[portName]; ok {
		return param
	}
	t.Failf("No such param port (%s)", portName)
	return "invalid"
}
func (t *Task) Tag(tagName string) string {
	if tag, ok := t.Tags[tagName]; ok {
		return tag
	}
	t.Failf("No such tag (%s)", tagName)
	return "invalid"
}
func (t *Task) Execute() {
	defer close(t.Done)
	if t.tempDirsExist() {
		t.Failf("Existing temp folders found, so existing. Clean up temporary folders (starting with %s) before restarting the workflow!", tempDirPrefix)
	}
	if t.anyOutputsExist() {
		t.Done <- 1
		return
	}
	t.workflow.IncConcurrentTasks(t.cores)  
	err := t.createDirs()                   
	if err != nil {
		t.Failf("Could not create directories: %v", err)
	}
	startTime := time.Now()
	if t.CustomExecute != nil {
		outputsStr := ""
		for oipName, oip := range t.OutIPs {
			outputsStr += " " + oipName + ": " + oip.Path()
		}
		t.Auditf("Executing: Custom Go function with outputs: %s", outputsStr)
		t.CustomExecute(t)
		t.Auditf("Finished: Custom Go function with outputs: %s", outputsStr)
	} else {
		t.Auditf("Executing: %s", t.Command)
		t.executeCommand(t.Command)
		t.Auditf("Finished: %s", t.Command)
	}
	finishTime := time.Now()
	t.writeAuditLogs(startTime, finishTime)
	t.ensureAllOutputsExist()
	finErr := t.finalizePaths()
	if finErr != nil {
		t.Fail(finErr)
	}
	t.workflow.DecConcurrentTasks(t.cores)
	t.Done <- 1
}