Bruno Luiz K.
Bruno Luiz K.

Reputation: 178

Strange behavior using read for validate string (bash script)

I are creating a .sh using bash for validate the api sub folders versions

The objective is validate this strings into APIS_BUILD var and find all .proto files into ./proto folder to compile into protobuffer Go file

# define subfolder apis to build
APIS_BUILD=(
    prototests/v1/
    prototests2/v2
    testfolder
)
# the "testfolder" are a invalid folder

Test cases:

prototestes/v1                      # valid
prototestes/v1/cobranca             # valid
prototestes/v1/cobrnaca/faturamento # valid
outrapastacomarquivosproto/v1       # valid
prototests                          # invalid
/prototests                         # invalid

Then, I created this script for validate the APIS_BUILD string array

#!/usr/bin/env bash

# text color
RED='\033[0;31m'  # RED
BLUE='\033[0;34m' # Blue
NC='\033[0m'      # No Color

# Underline color
UCyan='\033[4;36m' # Cyan

# define subfolder apis to build
APIS_BUILD=(
    prototests/v1
    cobrancas/v1
)
DST_DIR="."       # define the directory to store the build-in protofiles
SRC_DIR="./proto" # define the proto files folder

# Compile proto file
# $1 = Filename to compile
function compile() {
    protoc --go_out=$DST_DIR --proto_path=proto --go_opt=M$1=services \
        --go_opt=paths=import --go-grpc_out=. \
        $1
}

# Validate api_build's
function validateApiBuilds() {
    for t in ${APIS_BUILD[@]}; do
        IFS="/"
        read -a SUBSTR <<<"$t"
        if [ ${#SUBSTR[@]} -lt 2 ]; then
            printf "${RED}The API_BUILD value ${UCyan}\"${t}\"${RED} are declare wrong, please declare [api_folder]/[version_folder] (example: prototest/v1)${NC}\n" 1>&2
            exit 1
        fi
    done
}

validateApiBuilds

for filename in $(find $SRC_DIR -name '*.proto'); do
    [ -e "$filename" ] || continue
    echo $filename
done

enter image description here

But I getting a strange behavior:

Pictures:

With validateApiBuilds function:

enter image description here

Without validateApiBuilds function:

enter image description here


All the variables:

# define subfolder apis to build
APIS_BUILD=(
    prototests/v1
    cobrancas/v1
)
DST_DIR="."       # define the directory to store the build-in protofiles
SRC_DIR="./proto" # define the proto files folder

Bash version:

$ bash --version                                  
$ GNU bash, versão 4.4.19(1)-release (x86_64-pc-linux-gnu)

Obs.: I changed the validateApiBuilds function to use a regex validation for strings into API_BUILDS variable. But I really wanted to know the reason for this behavior.

edit 2: The make-proto.config file

# define subfolder apis to build
APIS_BUILD=(
    prototests/v1
    cobrancas/v1
)
DST_DIR="."       # define the directory to store the build-in protofiles
SRC_DIR="./proto" # define the proto files folder

Upvotes: 0

Views: 107

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295403

Use find better

for filename in $(anything) is always an antipattern -- it splits values on characters in IFS, and then expands each result as a glob. To make find emit completely unambiguous strings, use -print0:

while IFS= read -r -d '' filename; do
    [ -e "$filename" ] || continue
    echo "$filename"
done < <(find "$SRC_DIR" -name '*.proto' -print0)

Don't change IFS unnecessarily

Change your code to make the assignment to IFS be on the same line as the read, which will make IFS only be modified for that one command.

That is to say, instead of:

IFS=/
read -a SUBSTR <<<"$t"

...you should write:

IFS=/ read -a SUBSTR <<<"$t"

Upvotes: 1

Related Questions