1

This is probably a silly question, more out of curiosity. I have an array in bash:

array=(name1.ext name2.ext name3.ext)

I want to strip off the extension from each element. I was trying to do this by looping over each element, but I was having trouble setting the range of the loop (see below):

for i in 'echo {0..'expr ${#array[@]} - 1'}'; do newarray[$i]+=$(echo "${array[$i]:0:5}"); done

Please note ' = "back-tick" within the code-block because I wasn't sure how to escape it.

I'm not able to just use a set range (e.g. seq 0 3), because it changes based on the folder, so I wanted to be able to use the length of the array minus 1. I was able to work around this using:

for (( i=0; i<${#array[@]}; i++ )); do newarray[$i]+=$(echo "${array[$i]:0:5}"); done

But I thought there should be some way to do it with the "array length minus 1" method above and wondered how I was thinking about this incorrectly. Any pointers are appreciated.

Thanks! Dan

4
  • 1
    To quote the back tick inside a "back-ticked" block, just escape the back tick, for instance, escaped ` back tick. Commented Dec 21, 2016 at 17:34
  • I cannot understand what you want to get and what is the problem. Commented Dec 21, 2016 at 17:42
  • What I understood is that you want to run down an array by means of a sequence of indexes, instead of increasing a counter, but I do not catch the problem. Commented Dec 21, 2016 at 18:02
  • Sorry @Jdamian I was likely not being clear in my explanation. I wasn't so concerned with the output, but rather why I was unable to use for i in 'echo {0..'expr ${#{array[@]} - 1' to set an range from 0 to (array length - 1) Commented Dec 21, 2016 at 21:42

3 Answers 3

2

You can apply various parameter expansion operators to each element of an array directly, without needing an explicit loop.

$ array=(name1.ext name2.ext name3.ext)
$ printf '%s\n' "${array[@]%.ext}"
name1
name2
name3
$ newarray=( "${array[@]%.ext}" )

In general, though, there is nearly never any need to generate a range numbers to iterate over. Just use the C-style for loop:

for ((i=0; i< ${#array[@]}; i++ )); do
    newarray[$i]="${array[i]%.ext}"
done
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks very much @chepner for the good explanation. I do have one somewhat unrelated follow-up question. I am assigning my array with a wildcard, e.g. array=(name*.ext) and then use your suggestion to strip off the extension. However, when I call this variable later in a script: for i in ${newarray[@]}; do fslcommand "$i" input output; done it fails because the wildcard does not expand. Should I not be using a wildcard for array assignment?
The wildcard is expanded when you assign to array. However, if nothing matches the pattern, the array contains the literal pattern as its only element unless you set shopt -s nullglob previously. Make sure to quote the expansion in case any of the resulting file names contain whitespace or pattern metacharacters: for i in "${newarray[@]}"; do
Ok now I feel even more stupid. I wasn't setting the full path properly so of course it wasn't matching anything. Thanks for making me realize my error!
2

With Bash, you could simply loop over your array elements with ${files[@]}:

#!/bin/bash
files=(name1.ext name2.ext name3.ext)

for f in ${files[@]}; do
  echo "${f%.*}"
done

Also substring removal ${f%.*} is a better choice if you have extensions of different lengths.

1 Comment

in your solution the array has just one element, thus, no ${files[@]} is needed.
1

You can use the seq command

for i in `seq 0 $(( ${#array[@]} - 1 ))`
do 
      ···
done

or the bash brace expansion (but in this case you need eval):

for i in `eval echo {0..$(( ${#array[@]} - 1 ))}`
do 
      ···
done

But there is another better (it works even in sparse arrays): let's make bash give us the array indexes:

for i in ${!array[@]}
do 
      ···
done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.