just() { # use: ll=WIDTH just [ FILE ] # but you will first want to make sure length of lines does not exceed desired width if [ -f "$1" ]; then # a portable-ism for readarray while read text[ln++]; do :; done < "$1" else while read text[ln++]; do :; done fi ln=0 for line in "${text[@]}"; do if [ -z "${text[++ln]//[[:space:]]}" -o ${#line} -ge $ll -o ${#line} -le 1 ]; then # forgo justification on last line of each paragraph # as well as any line too long to be printed correctly printf '%s\n' "$line" else # this else is the original justify_line function from the editor :) (( ll )) || ll=60 w=($line) # words as an array wc=${#w[@]} # word count [ $wc -eq 1 ] && echo -n "$line" && return ch="${line// }" # non-whitespace characters ((wscol=ll-${#ch})) # number of whitespace columns ((spaces=wc>1?wc:1)) # number of spaces ((s=wscol/spaces)) # width of one space after justification ((f=wscol%spaces)) # leftover columns to achieve exact width ((m=wc/(f>1?f:2))) # word dividing the left and right alignment ((am=m>2?m-1:m)) # amended middle, further even out odd spaces # i is the index of the current word, c its length, S the final spacing and alignment for ((i=0,c=${#w[0]}; S=i<m?c+s:f?f--, c+s+1:c+s, S=i<am?-S:S, i<wc; c=${#w[++i]})); do fmt="${fmt}%${S}s" arg="${arg} ${w[i]}" done printf "$fmt\n" $arg unset fmt arg fi done unset text ln printf '\n' }