Expand the output of the command and only then assign it to a variable

Consider this task : With a one line command save all usernames transformed into CAPITALS in a bash array called USERNAMES. Capitalize using bash variable expansion.

If not for the the one line limitation, I would just use

USERNAMES=($(ls /home)) # simplified for purposes of this question, returns (user1 user2 ...)
USERNAMES=(${USERNAMES[*]^^}) # must return (USER1 USER2 ...)

but all attempts at nesting the first assignment to the variable expansion like USERNAMES=${($(ls /home))^^} or similar lead to ‘bad substitution’ error. I’m using bash 4.4.20(1)-release.

>Solution :

I use /* because you should not parse ls and I have only one dir in home.

readarray -t USERNAMES < <(printf "%s\n" /* | sed 's/.*/\U&/')
readarray -t USERNAMES < <(printf "%s\n" /* | tr '[:lower:]' '[:upper:]')
# or zero separated
readarray -t -d '' USERNAMES < <(printf "%s\0" /* | sed -z 's/.*/\U&/')
readarray -t -d '' USERNAMES < <(printf "%s\0" /* | tr -z '[:lower:]' '[:upper:]')
# Or another program
readarray -t USERNAMES < <(python -c 'import os,sys;[print(x.upper()) for x in os.listdir(sys.argv[1])]' /)
# You can hash _any_ multiline script to base64 and then execute it. It will be one line.
base64 -d <<<IyEvYmluL2Jhc2gKVVNFUk5BTUVTPSgkKGxzIC9ob21lKSkgIyBzaW1wbGlmaWVkIGZvciBwdXJwb3NlcyBvZiB0aGlzIHF1ZXN0aW9uLCByZXR1cm5zICh1c2VyMSB1c2VyMiAuLi4pClVTRVJOQU1FUz0oJHtVU0VSTkFNRVNbKl1eXn0pICMgbXVzdCByZXR1cm4gKFVTRVIxIFVTRVIyIC4uLikKZWNobyAiJHtVU0VSTkFNRVNbQF19Igo= | bash


Leave a Reply