Peteris Krumins has a fun post on performing set operations in shell. He skips over the powerset and instead writes it in perl. Which clearly is cheating. ;)

Bash has arrays that we don't have to index consecutively, so we just need to create a key() function that generates a unique numeric for each element. The key below works for numeric input. We could remove the key() function and accumulation in the array and instead just use "powerset 1 2 3 4 5 | sort | uniq". And that would be faster than the bash array work as well, but not pure shell. ;)

# create a numeric key for bash's array index key() { ret=0 i=0 for n in $*; do ret=$(( 2**${i} * ${n} + ${ret})) i=$((${i}+1)) done echo $ret } # recurse through subsets powerset_overkill() { local Set=$* if [ "${Set}" = "" ]; then return fi answer[ $( key ${Set} ) ]="${Set}" for i in ${Set}; do local Subset=${Set/${i}/} powerset_overkill ${Subset} done } # setup the array, and then start recursion powerset() { declare -a answer powerset_overkill $* for i in "${answer[@]}"; do echo $i done } time powerset 1 2 3