6

If I use bash's brace expansion I get a list

echo item={one,two,three}
item=one item=two item=three

Assuming I am in a directory with files/folders that would match a wildcard, is there any way to have an expansion that matches these files/folders?

ls
blue  green  red

echo item=* # Obviously not item=*

echo item={} # Maybe? ...but no item={}

In my example I would like the expansion to be item=blue item=green item=red

The best I've got so is code like this

items=()
for dirent in *; do items+=("item=$dirent"); done
echo "${items[@]}"

item=blue item=green item=red

Chris Davies
  • 116,213
  • 16
  • 160
  • 287
  • 2
    Do you want this as an array or as a string? Are you looking for something like printf 'item=%s ' *? – terdon Jun 15 '20 at 09:25
  • I see no issue with your loop. Is the intention to get a particular output or to modify the contents of the array? – Kusalananda Jun 15 '20 at 09:33
  • It's actually going to be an arguments array for interpolation into a command line (rsync --exclude...) – Chris Davies Jun 15 '20 at 09:36
  • This answer contains a workaround using eval (yes, I know, "evil eval") - but in light of the answers posted here, it is probably a lot less helpful than I originally thought ... – AdminBee Jun 15 '20 at 10:15
  • @AdminBee oh I see, yes. I don't think I can use that here because my files won't necessarily have taggable extensions (or indeed any fixed part of the file name) – Chris Davies Jun 15 '20 at 10:18

2 Answers2

8

You can store the current directory’s files in an array as follows:

items=(*)

Then parameter expansion can be used to add the prefix:

printf "%s\n" "${items[@]/#/item=}"

You can use this to update the array:

items=("${items[@]/#/item=}")
Stephen Kitt
  • 434,908
4

With zsh:

items=(*)
print -rC1 item=$^items

Or:

(){ print -rC1 item=$^@; } *

Or:

(){ print -rC1 ${@/#/item=}; } *

Or:

print -rC1 ./*(:s:./:item=)

Or:

set -o histsubstpattern
print -rC1 *(:s/#/item=)

Or:

print -rC1 *(e['REPLY=item=$REPLY'])

Or:

printf '%s%s\n' *(P[item=])

Or:

items=()
printf -v items 'item=%s' *
print -rC1 -- $items

etc.

For all of those add the N glob qualifier to get no output (or an empty line with the printf one) instead of an error if there's no matching file (here with *, that would be if the current directory is not readable or contains only hidden files).

Of course, if it's just about printing them, then you can just do (in any shell):

printf 'item=%s\n' *