The reason this is happening is because you have a file or subdirectory named C
in the directory where you are running the command and so the glob ?
is expanded to match it. To illustrate with a simpler example:
$ ls -la
total 92
drwxr-xr-x 2 terdon terdon 16384 Mar 26 18:53 .
drwxr-xr-x 170 terdon terdon 73728 Mar 26 13:57 ..
$ array=( $( printf '?\n' ) )
$ printf '%s\n' "${array[@]}"
?
Now, I create a file named C
and try again:
$ touch C
$ array=( $( printf '?\n' ) )
$ printf '%s\n' "${array[@]}"
C
This is down to the order of operations. When you run array=( $( printf '?\n' ) )
, what happens, in order, is:
- The
printf '?\n'
is executed and returns a ?
.
- The unquoted
?
is expanded by the shell to any matching file names, in this case one called C
.
- The expanded glob, the
C
, is stored as element 0
of the array array
.
To avoid this, you need to quote the array assignment so that any globbing characters are protected from the shell:
$ array=( "$( printf '?\n' )" )
$ printf '%s\n' "${array[@]}"
?
Or, with your original example:
$ array=( "$(grep -o -E '/ |:|\\|<|>|\*|\?|\"| $' <<< '/home/ttwaro/temp/Test/This is a Test: Testing Number 1?/This is Test: Testing Number 1?.eng.srt')" )
$ printf '%s\n' "${array[@]}"
:
?
:
?
However, because it is quoted, the entire result is presented as a single string and so the array will only have one element:
$ for ((i=0;i<${#array[@]}; i++)); do
printf 'element %s is %s\n' "$i" "${array[i]}";
done
element 0 is :
?
:
?
To get each result as a separate element in the array, you need to do something like this as suggested by Gordon Davisson in the comments:
$ readarray -t array < <(grep -o -E '/ |:|\\|<|>|\*|\?|\"| $' <<< '/home/ttwaro/temp/Test/This is a Test: Testing Number 1?/This is Test: Testing Number 1?.eng.srt')
$ for ((i=0;i<${#array[@]}; i++)); do
printf 'element %s is %s\n' "$i" "${array[i]}";
done
element 0 is :
element 1 is ?
element 2 is :
element 3 is ?
This will circumvent the need for quoting since the output of grep
is never seen by the shell.
Finally, the reason you got two C
s in your result is because each of the ?
was expanded to a C
when it was stored in the array:
$ array=( ? ? ? )
$ printf '%s\n' "${array[@]}"
C
C
C
C
in the current directory, that is matched by the unquoted?
glob perhaps??
on the first line then:
and then?
; I don't get the first ':", but no 'C's either.C
which is why they seeC
.array+=(? : ?)
which is globbing to the single character file. The reason I don't get the first:
is that the OP is using a different string after the<<<
in the two examples, which is confusing.