Just one file echoed from an array of files

It's Bash feature described in man bash:

Referencing an array variable without a subscript is equivalent to referencing the array with a subscript of 0.

If you want to print all members of files array:

echo "${files[@]}"

Also described in man bash:

${name[@]} expands each element of name to a separate word.

$files and ${files[0]} is equivalent when files is a list such as the one you have in your question.

Note that "source_path/${files[@]}" only puts source_path/ before the first element of the list. To modify the list in such a way that each element is prefixed by some path, you can do

files=( ... your list of files ... )

for element in "${files[@]}"; do
    files=( "${files[@]:1}" "source_path/$element" )

cp "${files[@]}" destanation_path

or, you could just cd to source_path before doing the cp, or add the path to the actual names at the same time as you assign the values in the list from the start.

As others have pointed out, $files only expands to the first element of the array, and "source_path/${files[@]}" only attaches "source_path/" to the first element. But there's a relatively simple way to get all elements, with a path prepended to each:

cp -a "${files[@]/#/source_path/}" "/destanation_path"

This combines the all-elements expansion ([@]) with a substitution. /# means "replace at beginning of string", then the empty string to replace, then / to delimit the replacement, then "source_path/" as the thing to replace (/add). This attaches the source path to each element, and doesn't get confused by funny characters in the elements like some versions do.

Note that in the above example, "source_path/" has a slash at the end but not the beginning; the "/" right before it is a delimiter. If it started with a slash and contained more slashes, like "/source/path/", it'd still work:

cp -a "${files[@]/#//source/path/}" "/destanation_path"