I have recently written some code in Bash where I'm starting to program some things and I think I'm overcomplicating the script I wrote.I'd like to make it simpler so that in future I would avoid these mistakes.I've posted this on Stack Overflow and one user did reply that I can simplify multi-echoing:just use 1 echo command, open with a double quote on the first line and close the quote after the last oneHere's the code:#!/bin/bash# Look for path when the skript isSCRIPT_PATH=$(readlink -f $0)SEARCH=$(dirname $SCRIPT_PATH)/ REPLACE=../../echoecho \ \ START - Replacing Absolute path to Relativeecho \ \ =================================================================echo \ \ Info: Automatic replacement of the \>absolute\< path echo \ \ to \>relative\< for the Pedestrian Tool positioning result filesecho \ \ =================================================================echoecho \ \ Searching for >>  $SEARCHecho \ \ Replacing by  >>  $REPLACEechoecho \ \ Found in files:echo \ \ =================echo# grep - filter files where inside is scripts path name and write them downgrep -rl ${SEARCH} --include \*.pc ./# replace them with sed ../../grep -rl ${SEARCH} --include \*.pc ./ | xargs sed -i s#${SEARCH}#${REPLACE}#gechoecho \ \ END - Replacing finished...echo \ \ =================================================================echo \ \ =================================================================echoecho echo \ \ START - Renaming Folders by Y-Coordinate of Impactorecho \ \ =================================================================echo \ \ Info: Script will look into RESULTS Folder, than find directoriesecho \ \ then find files in these directories and fromecho \ \ file named POSITIONING extcarc Y-Coordinate of the Impactorecho \ \ This value is then used to rename by the: MODEL_Y\$Y-Coordecho \ \ =================================================================echo# $SEARCH=path where the script is + /RESULTS/ where the results areadresar=$SEARCHRESULTS/directories=$(find $adresar*/ -type d)echoecho Folders in dir: $adresar:echofor d in $directoriesdo    echo \ Operations in folder: $d    files=$(find $d -type f )    for f in $files; do        fileExtension=${f##*.}        fullPathFileName=${f%.*}        fileName=$(basename $fullPathFileName)        # if Positioning_<#>.pc file        # find line that has Target POint Coordinates string        # example: # Target Point Coordinates  : -934.541, -100.000, 247.510        # and extract Y-coordinate without float, that is: -100        # can be 600 (without minus)        if [[ $fileExtension == pc && $fileName == Positioning_* ]]; then            line=$(grep Target Point Coordinates $f)            # -o (only matching) -E (extended-regexp)             # [^.](without dot)[0-9]+(variable number of numbers)            STRING=$(echo $line | grep -o -E '[^.][0-9]+')            N=3            yCoord=$(echo $STRING | awk -v N=$N '{print $N}')        fi    done    folderName=$(basename $d | tr 'a-z' 'A-Z')     if [[ $folderName != REPORT ]]; then        echo \ \ Dir $d renamed by Y-Coordinates of impactor        newFolderName=MODEL_Y$yCoord        cd $d; cd ..        mv $(basename $d) $newFolderName    fi    echodoneechoecho \ \ END - Renaming complete...echo \ \ =================================================================echo \ \ =================================================================echoechoecho \ \ START - Renaming .DSY, .msg, .THP files by folder nameecho \ \ =================================================================echo \ \ Info: Renames .DSY, .msg, .THP files in folder RESULTSecho \ \ by the name of parrent folder \(that is named by impactor\'secho \ \ Y-Coordinate \(\>\> MODEL_Y300\)echo \ \ =================================================================echodirectories=$(find $adresar*/ -type d)for d in $directoriesdo    echo \ Working in folder: $d    files=$(find $d -type f )    baseName=$(basename $d)    for f in $files; do        cd $d        fileExtension=${f##*.}        fullPathFileName=${f%.*}        fileName=$(basename $fullPathFileName)        Name=${baseName}.${fileExtension}          if [[ $fileExtension == 'pc' && $fileName != Positioning_* ]]; then            Name=${baseName}.${fileExtension}            mv $f $Name            echo \ \ Was renamed to: $Name        elif [ $fileExtension == 'DSY' ]; then            Name=${baseName}.${fileExtension}            mv $f $Name            echo \ \ Was renamed to: $Name        elif [ $fileExtension == 'THP' ]; then            Name=${baseName}.${fileExtension}            mv $f $Name            echo \ \ Was renamed to: $Name        elif [ $fileExtension == 'msg' ]; then            Name=${baseName}.${fileExtension}            mv $f $Name            echo \ \ Was renamed to: $Name        else            echo \ \ X Wasn't renamed.        fi        echo \ =====    done    echodoneecho \ \ END - Renaming complete...echo \ \ =================================================================echo \ \ =================================================================echo -e \n
Optimising script that does simple renaming of files
performance;bash;shell
Simplifying the echo statementsYour question on SO suggests that you're particularly interested in simplifying all those echo statements.A feature called here-documents can help you, for example:cat <<EOF  START - Replacing Absolute path to Relative  =================================================================  Info: Automatic replacement of the >absolute< path   to >relative< for the Pedestrian Tool positioning result files  =================================================================  Searching for >>  $SEARCH  Replacing by  >>  $REPLACE  Found in files:  =================EOFNotice that this way you can also omit many quotes and escapes.Speaking of quoting, sometimes you quote too much.For example, instead of this:SEARCH=$(dirname $SCRIPT_PATH)/You could write:SEARCH=$(dirname $SCRIPT_PATH)/Danger! Watch out for falling rocks!Storing the output of find and then iterating over it is error prone.I mean this kind of code:directories=$(find $adresar*/ -type d)for d in $directoriesThe problem with this is that it won't work with subdirectories that have a space in their name. This is because in the for loop, the shell splits the value of $directories by any whitespace character (space, tab, newline), not only newline, as in the output of find.For example if you have a subdirectory named a b, find will output it on its own line,but when you iterate over $directories, the shell will split the line of a b in the middle.This splitting is defined by the variable IFS,you can read about it in man bash.One way to make your commands safe is to set IFS to newline, like this:oldIFS=$IFSIFS=$'\n'directories=$(find $adresar*/ -type d)for d in $directories; do    # do work ...doneIFS=$oldIFS