I am trying to "beautify" scripts automatically by using declare -f function

In a nutshell: Given a bash script foo , you can apparently "automagically" indent it by doing, in bash: MAGIC () { ...here you copy/paste the whole foo script... ; } ; declare -f MAGIC

I provide an example script below that does that for any script you give it as input.

My question is : what are the main caveats of using an encompassing function and then declare -f it ?

  • any special dangers?
  • limit on the number of function nesting ? (I can have functions in the script, they are happily indented as well, but how many levels deep can I go?)
  • "won't be able to do this/interpret that/..." ? (it seems awk script get fine, and are even indented a bit (the main script is aligned to the rest of the script) ... but what (other) things could pose problems?
  • will lose some informations? I noticed: it removes blank lines, and comments (# ...), but what else does it discard/modify?

I want to get your input before I can use my "indent" script below to reindent a bunch of bash scripts...

Here is my first attempt, comments (and answers about concerns above) welcomed :

 # parameters:  $@ = bash (only) scripts that need reindentations.

for script in "$@" ; do
  # optionnal temporisation...
  echo "I am about to create ${script}.BEAUTIFY from the bash (I hope) script: ${script} . Press return if OK, ctrl-C if not"
  read temporisation
  # we output the following commands into a pipe to a subshell bash:
  { sleep 1
    echo "
      # declare surrounding function . The script has to be bash, but can contain also functions, etc.
      # Will lose # comments and blank lines, but maybe also other things... hence the Question on unix.se
      $(cat "$script")
      #  print if via declare -f, to pretiffy it
      declare -f ODBEAUTIFIER > \"${tmpfile}\"
      #  then get rid of the surrounding ODBEAUTIFIER function:
      tail -n +3 \"${tmpfile}\" | tac | tail -n +2 | tac | sed -e 's/    //' > \"${finalfile}\"
      #  and displays the resulting file
      ls -l \"${script}\" \"${finalfile}\"
      \rm \"${tmpfile}\" ; # that rm has a backslash to avoid aliases to rm -i
   } | bash ; #  that sub- bash receives the input and interprets it

Note/edit: There is a workaround (but with many caveats and dangers) to avoid the "declare -f will lose comments starting with #": but it seems it distracts (... at least one insisting user, see comments below ^^) from the main question (Even tough I cited the many caveats of the workaround, I prefer to remove its mention above as it wasn't at all the point of the question. Curious minds may refer to the edit before now ^^ )


There's a security risk with reading in the script as a function then piping to another shell: If the input file contains an unmatched }, then whatever follows it will be executed (and omitted from the output).

An unmatched } could come about accidentally or maliciously. It would normally cause bash to report a syntax error, but an attacker could hide this (from the user running the beautify script) by ending the file with another, unfinished function:

echo "insert shellcode here" > ~/RCFILE
function end_func {

Less important:

  • You've mentioned that it loses comments starting with #. That includes the opening #!/bin/..., so it may prevent the output files from running.

  • sed -e 's/ //' strips the first 4 spaces in any line. Those are usually the 4 spaces prepended by declare. But declare doesn't insert spaces before the lines of a here-document, so this may delete other spaces that were part of the original.

  • You could use head -n -1 instead of tac | tail -n +2 | tac. Or you could remove both tails and use sed '1,2d;$d'.

  • I like your remarks, except the security one (a first ^^). : the script can be run as a very low proviledge user, and I also won't use it on other scripts than my own... But it's true it could indeed be used to insert something.. at the cost of making the original script doing it too (or not being syntaxivcally correct, in your example). thx for your input. – Olivier Dulac May 8 '16 at 19:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.