Is looping through one by one the most efficient way to [perform substitutions on the filenames]?
No, nor is it the most efficient way to to extract the base names. Nor, for that matter, is it wise to parse the output of ls, though this is a relatively benign case. If you want to massage a list of filenames then passing the whole list through one sed or awk process is a better approach. For example:
file_list="$(
find ~/Desktop/test -mindepth 1 -maxdepth 1 -not -name '.*' |
sed 's,^.*/,,; s,^test,this,'
)"
That find command outputs paths to the non-dotfiles in the specified directory, one per line, much as ls would do. sed then attempts two substitutions on each one: the first removes everything up to and including the last / character, ala basename, and the second substitutes this for test where the latter appears at the beginning of what's left of the line.
Note also that this approach, like your original one, will have issues with filenames containing newlines. It doesn't have an inherent issue with file names containing other whitespace, but you will have trouble interpreting the results correctly if any of the file names contain whitespace.
file_list="$(ls ~/Desktop/test | while read path; do basename "$path" | cut -f 1 -d '.'; done)". I just made a folder there and put some text files in, and it worked for me. I am just clipping out the extension of .txt too.users/unamein any of the names when you are processing them throughbasename? Or when you are generating them in the first place withls test, for that matter?basenameandcut. We need to understand the context to give you good advice, and what you have presented is inconsistent.file_list=(*); file_list=( "${file_list[@]/#test/this}" )may be sufficient.