0

I am trying to compare an array with a value and print an error statement if the match is not found.

arraylist="$(ls new-dir/ | cut -d' ' -f1)"

For example, this stores values such as small, large and medium which are the files present in new-dir. The value to be compared with will be entered by the user viz. var

I have tried something like following:

(for i in "${arraylist[@]}"; do [[ "$i" == "$var"]] && exit 0; done) && echo "found" || echo "not found"

Also tried, however, doesn't work:

arraylist="$(ls new-dir/ | cut -d' ' -f1)"
count=0

for((i=0; i<${#arraylist[@]}; i++)); do
  if [ "$arraylist[$i]" == "$var" ] ; then
    count=1
  fi
done

if [ $count -eq 0 ]; then
  echo "Not found"
fi

Is there any other way to do this comparison?

John Kugelman
  • 307,513
  • 65
  • 473
  • 519
AishwaryaK
  • 51
  • 6
  • Your syntax to access an array element is wrong. It should have been `${arraylist[$i]}` or `${arraylist[i]}`, since this is an indexed array. And, [Why you shouldn't parse the output of ls](https://mywiki.wooledge.org/ParsingLs). – M. Nejat Aydin Mar 10 '21 at 14:52
  • 1
    The whole snippet above could be reduced to `[[ -e new-dir/$var ]] || echo "Not found"` (if it was syntactically correct). – M. Nejat Aydin Mar 10 '21 at 15:17
  • `arraylist="$(` that's not an array. That's a normal variable. https://stackoverflow.com/questions/3685970/check-if-a-bash-array-contains-a-value answers your question? – KamilCuk Mar 10 '21 at 15:18
  • Thanks for the help. Is there any way in which fetch the files from the directory and store it in an array without manually forming an one? – AishwaryaK Mar 10 '21 at 15:24
  • @AishwaryaK I don't know what you mean by "without manually forming", but this can be done easily: `files=(dirname/*)`. Note that the array will also contain non-regular files, if any, and won't contain filenames beginning with a `.`, by default. – M. Nejat Aydin Mar 10 '21 at 16:06

4 Answers4

1

This code works. Just replace arraylist with your array.

arraylist=('hello' 'world')
var='hello'
count=0

for i in "${arraylist[@]}"
do
    if [ "$i" == "$var" ]; then
        count=1
    fi
done

if [ $count -eq 0 ]; then
  echo "Not found"
fi
John Kugelman
  • 307,513
  • 65
  • 473
  • 519
user15239442
  • 34
  • 1
  • 4
1

To extract the first "word" from each filename, I'd do

declare -A prefixes
cd new-dir
for file in *; do
    read -r prefix _ <<< "$file"
    prefixes["$prefix"]=1
done
cd -

then to look for a match:

# $var is somehow provided
result=""
for p in "${!prefixes[@]}"; do
  if [[ $p == "$var" ]]; then
    result=found
    break
  fi
done
echo "${result:-not found}"

This requires bash v4.0+ for the use of an associative array.

If you have bash v4.3+ you can do

[[ -v prefixes[$var] ]] && echo found || echo not found

Alternately:

shopt -s nullglob
files=( new-dir/"$var "* )
(( ${#files[@]} > 0 )) && echo found || echo not found
glenn jackman
  • 207,528
  • 33
  • 187
  • 305
-1

The arraylist might be an array with just one index.

The command: arraylist="$(ls new-dir/ | cut -d' ' -f1)" might just assign whole "ls new-dir" output to ${arraylist[0]}

You can check the index value in an array by echo ${arraylist[1]} (to confirm).

Try changing the command to generate an array for a list of files/dirs to:

arraylist=($(ls new-dir/))

The complete script:


arraylist=($(ls new-dir/))

(for i in "${arraylist[@]}"; do [[ "$i" == "$var" ]] && exit 0; done) && echo "found" || echo "not found"

You can also ignore the whole array assignment and just use subshell-command in for loop, eg:

(for i in $(ls -1 new-dir/); do [[ "$i" == "$var" ]] && exit 0; done) && echo "found" || echo "not found"

Remember, no quotes " around $(ls -1 new-dir/)


Another one-liner without any array or loops:

ls -1 new-dir/ | grep -q "$var" && echo "found" || echo "not found"

Edit: As @M. Nejat Aydin suggested, use [[ -e new-dir/$var ]] && echo "found" || echo "Not found" and do not use ls in the script.

VDR
  • 2,223
  • 1
  • 14
  • 12
  • "a simple one-liner" could be even simpler without external commands `ls` and `grep` and subshell: `[[ -e k8s_apps/$var ]] && echo "found" || echo "Not found"` – M. Nejat Aydin Mar 10 '21 at 16:53
  • @M.NejatAydin Well, you have already shared the same one-liner as a comment to OPs question. I didn't think it is a good idea to repeat the answer. The idea here is to provide alternatives. – VDR Mar 10 '21 at 18:31
  • 1
    The problem is that, it isn't an alternative; it may fail in many cases. For example, the variable `var` may contain spaces or wildcard characters (such as `*`). Also filenames may contain some weird characters. The use of `ls` isn't a correct way to get the list of files within a script. – M. Nejat Aydin Mar 10 '21 at 18:50
-1

This is what shell programming is about. Keep it simple :

Array1=( "item1" "item2" "item3" "item-4" )
var="item3"

count=$(echo ${Array1[@]} | tr ' ' '\n' | awk '$1 == "'"$var"'"{print $0}' | wc -l)
[ $count -eq 0 ] && echo "Not found" || echo "found"
Mahmoud Odeh
  • 887
  • 1
  • 4
  • 16
  • I've downvoted just because I don't find this answer useful and it may fail in many cases; for example when array elements contain spaces or wildcard characters. And my comment wasn't intended as a solution. – M. Nejat Aydin Mar 10 '21 at 18:02