Score:2

How to get a list of all terminal commands used by a .sh file with Bash, i.e. a list of the dependencies of the .sh script

ng flag

Given are a PC which use Ubuntu. How to output by bash on screen or on file, a list of all by the .sh file used terminal commands? The output of the commands are not need on runtime. I don't expect any output from the given script, I just want to determine the commands used in the script and save them e.g. in a new file to be created.

Follow a sample of a .sh file:

#!/bin/bash

# Some comments, comments, comments

echo "######################"
echo "# FF_groesse_position"
echo "######################"
echo
echo

######################
# Variables
######################
sleep=5

######################
echo "Programm area"
######################

firefox
sleep 5

echo
echo

x=$(xdotool getdisplaygeometry | cut -d ' ' -f1 )
y=$(xdotool getdisplaygeometry | cut -d ' ' -f2 )
echo "x=$x"
echo "y=$y"

echo
echo

x=$(wmctrl -lG | grep Desktop | tr -s ' ' | cut -d ' ' -f5 )
y=$(wmctrl -lG | grep Desktop | tr -s ' ' | cut -d ' ' -f6 )

echo "x=$x"
echo "y=$y"

echo
echo

read -p "Press Enter or Ctl + C"

Wanted output:

echo
echo
echo
echo
echo
echo
firefox
sleep
echo
echo
xdotool
cut
xdotool
cut
echo
echo
echo
echo
wmctrl 
grep 
tr 
cut
wmctrl 
grep 
tr 
cut
echo
echo
echo
read

Perhaps, its possible to get the list of by .sh file used commands by the command compgen like about the follow:

compgen -c file.sh > found_commands.txt

Or by like about the follow:

set -option file.sh > found_commands.txt

Or on other way by bash.

Asked are a answer in follow form:

command -option file.sh > found_commands.txt
David avatar
cn flag
Sorry I do not understand the question. Could you please reword it? what does output on Ubuntu mean?
pLumo avatar
in flag
what output do you expect from from given script ?
lnee avatar
td flag
try replaceing `#!/bin/bash` with `#!/bin/bash -x `
muru avatar
us flag
Even if some program was able to generate this output for this script, no program will be able to generate the output for, say, `cd /some/directory; *`, or `read foo; $foo`, or `(( $RANDOM < $RANDOM)) && a || b`. So the set of possible scripts that can be parsed will need to be constrained. What are the constraints?
Alfred.37 avatar
ng flag
@ meru, I dont understand your question. I like to get a list of commands from one file. Perhaps you can call it a list of dependencies, also.
muru avatar
us flag
Yes, and what output do you think is right for the example scripts in my comment?
Alfred.37 avatar
ng flag
@lnee, The scripts to be examined should not be changed, so what is a #!/bin/bash -x should be achieved from outside the script.
Score:5
vn flag

You can use set -x in you script, and combine it with redirecting the error stream 2> to a file.

So at the beginning of your script, use either:

#!/bin/bash -x

Or

#!/bin/bash
set -x

Then, run your script like this:

./file.sh 2> found_commands.txt

For your script, the resulting file would be:

+ echo "######################"
+ echo "# FF_groesse_position"
+ echo "######################"
+ echo
+ echo
+ sleep=5
+ echo "Programm area"
+ firefox
+ sleep 5
+ echo
+ echo
++ xdotool getdisplaygeometry
++ cut -d ' ' -f1
+ x=$(xdotool getdisplaygeometry | cut -d ' ' -f1 )
++ xdotool getdisplaygeometry
++ cut -d ' ' -f1
+ y=$(xdotool getdisplaygeometry | cut -d ' ' -f2 )
+ echo "x=$x"
+ echo "y=$y"
+ echo
+ echo
++ wmctrl -lG
++ grep Desktop
++ tr -s ' '
++ cut -d ' ' -f5
+ x=$(wmctrl -lG | grep Desktop | tr -s ' ' | cut -d ' ' -f5 )
++ wmctrl -lG
++ grep Desktop
++ tr -s ' '
++ cut -d ' ' -f5
+ y=$(wmctrl -lG | grep Desktop | tr -s ' ' | cut -d ' ' -f6 )
+ echo "x=$x"
+ echo "y=$y"
+ echo
+ echo
+ read -p "Press Enter or Ctl + C"

You can then process your output file, and remove all variable definitions with the following Regular Expression*

egrep -v "^\++\ ([a-zA-Z])\w*\=" found_commands.txt

resulting in:

+ echo "######################"
+ echo "# FF_groesse_position"
+ echo "######################"
+ echo
+ echo
+ echo "Programm area"
+ firefox
+ sleep 5
+ echo
+ echo
++ xdotool getdisplaygeometry
++ cut -d ' ' -f1
++ xdotool getdisplaygeometry
++ cut -d ' ' -f1
+ echo "x=$x"
+ echo "y=$y"
+ echo
+ echo
++ wmctrl -lG
++ grep Desktop
++ tr -s ' '
++ cut -d ' ' -f5
++ wmctrl -lG
++ grep Desktop
++ tr -s ' '
++ cut -d ' ' -f5
+ echo "x=$x"
+ echo "y=$y"
+ echo
+ echo
+ read -p "Press Enter or Ctl + C"

Finally, you can extract only the second word of each line with

egrep -v "^\++\ ([a-zA-Z])\w*\=" found_commands.txt | cut -d ' ' -f2 }'

resulting in:

echo
echo
echo
echo
echo
echo 
firefox
sleep
echo
echo
xdotool
cut
xdotool
cut
echo
echo
echo
echo
wmctrl
grep
tr
cut
wmctrl
grep
tr
cut
echo
echo
echo
echo
read

You can combine it into a single command using Bash subshells and redirection, like this:

./file.sh 2> >(egrep -v "^\++\ ([a-zA-Z])\w*\=" | cut -d ' ' -f2 > found_commands.txt)

Now the file found_commands.txt will have the processed output.

If you don't want duplicates, and only want to know which commands are run, filter through sort-u (unique option) with

./file.sh 2> >(egrep -v "^\++\ ([a-zA-Z])\w*\=" | cut -d ' ' -f2 | sort -u > found_commands.txt)

resulting in an alphabetic list of "dependencies" for the script:

cut
echo
firefox
grep
read
sleep
tr
wmctrl
xdotool

*RegEx breakdown

  • ^ beginning of line
  • \+ plus sign
  • + 1 or more of the preceding element
  • \ space
  • ( begin group
  • [a-z][A-Z] any English letter
  • ) end group
  • \w word character (a-z, A-Z, 0-9 and _)
  • * 0 or more of the preceeding element
  • \= equal sign
Alfred.37 avatar
ng flag
its looks good for me. THX. One bonus wish, if its possible on easy way. Its possible to do it without awk, only by bash core utilitys ...
Artur Meinild avatar
vn flag
Is using `cut` instead of `awk` good? Should be easy..
Alfred.37 avatar
ng flag
cut wil be perfect.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.