I'm trying to write a program that will allow easier management of Arduino projects. So I wrote bash script that creates all the necessary folders and files for me and when I execute it I runs like champ. Because I want to change directory in the working terminal inside the script I run script like this
. ./initialize.sh
This is also working great, but because I am writing C++ program, sourcing this script from program is giving me headache.
So inside a program I run this script like this:
system(". /usr/lib/avrduino/script/initialize.sh");
and then when I run the program I get this error:
sh: 25: /usr/lib/avrduino/script/initialize.sh: Syntax error: "(" unexpected (expecting "}")
Running the script from the program like this:
system("/usr/lib/avrduino/script/initialize.sh");
works without error but it runs in subshell.
Syntax error points to this line in script
options=("uno" "mega" "mega2560" "atmega8" "atmega168" "atmega328" "pro" "pro5v" "pro328" "pro5v328")
How come that when I run this script outside of the program it's working like champ, but run this script from program and you have a problem ?
EDIT:
Script code
#!/bin/bash
BLACK='\033[0;30m'
RED='\033[0;31m'
GREEN='\033[0;32m'
BROWN='\033[0;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
LGRAY='\033[0;37m'
DGRAY='\033[1;30m'
LRED='\033[1;31m'
LGREEN='\033[1;32m'
YELLOW='\033[1;33m'
LBLUE='\033[1;34m'
LPURPLE='\033[1;35m'
LCYAN='\033[1;36m'
WHITE='\033[1;37m'
NC='\033[0m'
makefile()
{
BOARD="default"
PS3='Chose your board: '
options=("uno" "mega" "mega2560" "atmega8" "atmega168" "atmega328" "pro" "pro5v" "pro328" "pro5v328")
select opt in "${options[#]}"
do case $opt in
"uno") BOARD="uno"
cp -r /usr/lib/avrduino/data/boards_info/uno/board-info.h .
MCU="atmega328P"
F_CPU="16000000UL"
;;
"mega") BOARD="mega"
cp -r /usr/lib/avrduino/data/boards_info/mega/board-info.h .
F_CPU="16000000UL"
;;
"mega2560") BOARD="mega2560"
cp -r /usr/lib/avrduino/data/boards_info/mega2560/board-info.h .
F_CPU="16000000UL"
;;
"atmega8") BOARD="atmega8"
cp -r /usr/lib/avrduino/data/boards_info/atmega8/board_-nfo.h .
MCU="atmega8"
F_CPU="16000000UL"
;;
"atmega168") BOARD="atmega168"
cp -r /usr/lib/avrduino/data/boards_info/atmega168/board-info.h .
MCU="atmega168"
F_CPU="16000000UL"
;;
"atmega328") BOARD="atmega328"
cp -r /usr/lib/avrduino/data/boards_info/atmega328/board-info.h .
MCU="atmega328P"
F_CPU="16000000UL"
;;
"pro") BOARD="pro"
cp -r /usr/lib/avrduino/data/boards_info/pro/board-info.h .
MCU="unknow"
F_CPU="16000000UL"
;;
"pro5v") BOARD="pro5v"
cp -r /usr/lib/avrduino/data/boards_info/pro5v/board-info.h .
MCU="unknown"
F_CPU="16000000UL"
;;
"pro328") BOARD="pro328"
cp -r /usr/lib/avrduino/data/boards_info/pro328/board-info.h .
MCU="atmega328P"
F_CPU="16000000UL"
;;
"pro5v328") BOARD= "pro5v328"
cp -r /usr/lib/avrduino/data/boards_info/pro5v328/board-info.h .
MCU="atmega328P"
F_CPU="16000000UL"
;;
*)
echo "Error : Input is not valid"
echo "Exiting..."
return 1
;;
esac
break
done
[ -e Makefile ] && rm Makefile
read -p "Do you want to configure your Makefile settings [Y/n]: " CONFIGURE
if { [ "$CONFIGURE" == "Y" ] || [ "$CONFIGURE" == "y" ]; }; then
read -p "Enter your MCU: " MCU
read -p "Enter F_CPU: " F_CPU
fi
read -p "Enter ARDUINO_PORT: " ARDUINO_PORT
echo "ARDUINO_DIR = /usr/share/arduino">>Makefile
echo "BOARD_TAG = $BOARD">>Makefile
echo "ARDUINO_PORT = $ARDUINO_PORT">>Makefile
echo "NO_CORE = 1">>Makefile
echo "AVRDUDE_ARD_PROGRAMMER = arduino">>Makefile
echo "HEX_MAXIMUM_SIZE = 30720">>Makefile
echo "AVRDUDE_ARD_BAUDRATE = 115200">>Makefile
echo "#ISP_LOW_FUSE = 0xFF">>Makefile
echo "#ISP_HIGH_FUSE = 0xDA">>Makefile
echo "#ISP_EXT_FUSE = 0x05">>Makefile
echo "#ISP_LOCK_FUSE_PRE = 0x3F">>Makefile
echo "#ISP_LOCK_FUSE_POST = 0x0F">>Makefile
echo "MCU = $MCU">>Makefile
echo "F_CPU = $F_CPU">>Makefile
echo "VARIANT = standard">>Makefile
echo "ARDUINO_LIBS =">>Makefile
echo "include /usr/share/arduino/Arduino.mk">>Makefile
echo "$BOARD|$MCU|" >> .avrduino.txt
clear
echo -e "${LGREEN}Makefile settings${NC}"
echo -e "${LBLUE}ARDUINO_DIR = ${LRED}/usr/share/arduino ${NC}"
echo -e "${LBLUE}BOARD_TAG = ${LRED}$BOARD${NC}"
echo -e "${LBLUE}ARDUINO_PORT = ${LRED}$ARDUINO_PORT${NC}"
echo -e "${LBLUE}NO_CORE = ${LRED}1${NC}"
echo -e "${LBLUE}AVRDUDE_ARD_PROGRAMMER = ${LRED}arduino${NC}"
echo -e "${LBLUE}HEX_MAXIMUM_SIZE = ${LRED}30720${NC}"
echo -e "${LBLUE}AVRDUDE_ARD_BAUDRATE = ${LRED}115200${NC}"
echo -e "${DGRAY}#ISP_LOW_FUSE = ${RED}0xFF${NC}"
echo -e "${DGRAY}#ISP_HIGH_FUSE = ${RED}0xDA${NC}"
echo -e "${DGRAY}#ISP_EXT_FUSE = ${RED}0x05${NC}"
echo -e "${DGRAY}#ISP_LOCK_FUSE_PRE = ${RED}0x3F${NC}"
echo -e "${DGRAY}#ISP_LOCK_FUSE_POST = ${RED}0x0F${NC}"
echo -e "${LBLUE}MCU = ${LRED}$MCU${NC}"
echo -e "${LBLUE}F_CPU = ${LRED}$F_CPU${NC}"
echo -e "${LBLUE}VARIANT = ${LRED}standard${NC}"
echo -e "${LBLUE}ARDUINO_LIBS =${NC}"
}
initializeProject()
{
read -p "Project name: " PROJECT_NAME
if [ ! -e PROJECT_NAME ]; then
mkdir $PROJECT_NAME
cd $PROJECT_NAME
makefile #Call function that makes makefile
cp -r /usr/lib/avrduino/data/include/ .
echo -e "${LGREEN}Project created successfully ${NC}"
else
echo "AVRduino: Project with name [ $PROJECT_NAME ] already exists. "
echo "AVRduino: Stop project wizard and exit."
fi
}
clear
initializeProject
. doesn't execute the script as a process, it only loads it into your current shell process.
In that context, your "shebang" line, #!/bin/bash, is just a comment.
(You can put #! doodle poodle noodle there and it will run just as well.)
When you use system, it executes in /bin/sh, and thus your bash script has syntax errors.
One way to execute scripts is to make them executable:
chmod +x /usr/lib/avrduino/script/initialize.sh
and then you can just pass it directly to system:
system("/usr/lib/avrduino/script/initialize.sh");
Or, you could explictly execute it in bash:
system("/bin/bash /usr/lib/avrduino/script/initialize.sh");
OK, here's a way one might solve your "changing directory" problem:
Rewrite initialize.sh so it takes the project name as an argument instead of asking for it interactively (that's how normal Unix tools work, so stick with it).
Then add the following to your .bashrc:
make_project()
{
/usr/lib/avrduino/script/initialize.sh "$1" && cd "$1"
}
Then you can say make_project foo and get transported to the directory "foo".
Most likely it is the misplaced shebang causing a default shell to be run - make sure the shebang is at the beginning of the first line
#!/bin/bash
# rest of script
If that does not work change your system call to
system("/bin/bash /usr/lib/avrduino/script/initialize.sh");
Related
I wanted to create a function in bash similar to a default alias I got in Ubuntu, looking like:
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
This creates a simple notification after a command has been issued with it.
For example, using
history | grep vim; sleep 5; alert
gives a notification after the sleep is done, simply saying
history | grep vim; sleep 5;
I would like to write the alert into a bash function instead, which have given some trouble with the regex.
I have tried:
function alert2 () {
ICON=$([ $? = 0 ] && echo terminal || echo error)
MSG=$(history | tail -n1 | sed -e s/^\s*[0-9]\+\s*//\;s/[\;\&\|]\s*alert$//)
notify-send --urgency=low -i $ICON $MSG
}
which would output both the linenumber in history when called itself, and give an Invalid number of options when called such as the first example.
Is this possible, and if so, how? Is it simply my regex that is faulty?
I'm running on WSL, so don't have notify-send installed:
function alert2 () {
ICON=$([ $? = 0 ] && echo terminal || echo error);
MSG=$(history | tail -n1| sed -e 's/^\s*[0-9]\+\s*//;s/[;&|]\s*alert2$//');
echo $ICON $MSG;
}
jadams#Temp046317:~/code/data-extract$ cat /etc/apt/sources.list > /dev/null ; alert2
terminal cat /etc/apt/sources.list > /dev/null
I'm hoping that this would work for you (instead of the echo):
notify-send --urgency=low -i "$ICON $MSG"
I have a function read_command defined as:
function read_command {
local __newline __lines __input __newstr __tmp i;
exec 3< "$*";
__newline=$'\n';
__lines=();
while IFS= read <&3 -r __line && [ "$__line" != '####' ]; do
echo "$__line";
__lines+=("$__line");
done
while IFS= read <&3 -r __line && [ "$__line" != '####' ]; do
read -e -p "${__line#*:}$PS2" __input;
local ${__line%%:*}="$__input";
done
__command="";
for i in "${__lines[#]}"; do
__tmp=$(echo "${i}");
__command="${__command} ${__newline} ${__tmp}";
done
echo -e "$__command";
}
In the current directory there is a file named "test", with the following
content:
greet ${a:-"Bob"}
greet ${b:-"Jim"}
####
a: name of friend a
b: name of friend b
####
In the terminal, the command executed is
read_command test
With no input, I am expecting the output of the last statement to be:
greet Bob
greet Jim
But what I get is:
greet ${a:-"Bob"}
greet ${b:-"Jim"}
What is wrong here?
Edit: As suggested by David, adding eval works in some cases except the following one.
j=1;i="export DISPLAY=:0 && Xephyr :${j}&";k=$(eval echo "$i");
echo $k
export DISPLAY=:0
I am expecting k to be "export DISPLAY=:0 && Xephyr :1&", what's wrong here?
Edit: I tried with the following
k=$(eval "echo \"$i\"")
This is the link to the script I am working on.
https://gist.github.com/QiangF/565102ba3b6123942b9bf6b897c05f87
During the first while loop, in echo "$__line", you have __line='greet ${a:-"Bob"}'. When you try to print that, Bash won't be expanding ${a:-"Bob"} into Bob. (Even if you remove the quotes around $__line this won't happen.) To get that effect, you need to add eval, as in, e.g., eval echo "$__line". Unfortunately eval comes with its can of worms, you have to start worrying about interactions between quoting levels and such.
My specific problem is not the fact that source /venv/bin/activate is being executed everytime I change to a sub folder. The problem is everytime I do it prints "will run" /path/to/.env
I installed autoenv through homebrew in version 0.2.0. This is my .env file:
if [ -z "$VIRTUAL_ENV" ]; then
CUR_DIR=$(pwd)
# search for the next .env
while [[ "$PWD" != "/" && "$PWD" != "$home" ]]; do
env_file="$PWD/.env"
if [[ -f "$env_file" ]]; then
BASE_DIR=$(dirname $env_file)
break
fi
builtin cd ..
done
if [ ! -z "$BASE_DIR" ]; then
echo "Activating that virtualenv"
source ${BASE_DIR}/venv/bin/activate
fi
cd $CUR_DIR
fi
The output in the terminal is something like:
MacBook-Pro:~ llamasramirez$ cd Desktop/oficios/
Will run /Users/llamas/Desktop/oficios/.env
Activating that virtualenv
Will run /Users/llamas/Desktop/oficios/.env
(venv) MacBook-Pro:oficios llamasramirez$ cd django_sites/polls/
Will run /Users/llamas/Desktop/oficios/.env
(venv) MacBook-Pro:polls llamasramirez$
Turns out the problem wasn't in the .env file. The problem was at the activate.sh file.
Opening the autoenv_init function there's a for loop that makes the annoying echo instruction:
for _file in ${_orderedfiles}; do
echo "Will run ${_file}"
autoenv_check_authz_and_run "${_file}"
done
When I comment this the echo doesn't pops up again.
I am attempting to build the ACE library for Mingw GCC 64 bit on Windows. The instructions here state the following:
Install the MinGW tools (including the MinGW Development toolkit) into a common directory, say c:/mingw.
Install the MSYS tools into a common directory, say c:/msys.
Open a MSYS shell. Set your PATH environment variable so your MinGW's bin directory is first:
% export PATH=/c/mingw/bin:$PATH
Add an ACE_ROOT environment variable pointing to the root of your ACE wrappers source tree:
% export ACE_ROOT=/c/work/mingw/ACE_wrappers
From now on, we will refer to the root directory of the ACE source tree as $ACE_ROOT.
Create a file called config.h in the $ACE_ROOT/ace directory that contains:
#include "ace/config-win32.h"
Create a file called platform_macros.GNU in the $ACE_ROOT/include/makeinclude directory containing:
include $(ACE_ROOT)/include/makeinclude/platform_mingw32.GNU
In the above text, don't replace $(ACE_ROOT) with the actual directory, GNU make will take the value from the environment variable you defined previously.
If you lack Winsock 2, add the line
winsock2 = 0
before the previous one.
If you want to install ACE (using "make install") and want all the .pc files generated, set the installation prefix in platform_macros.GNU.
INSTALL_PREFIX=/c/ACE
Headers will be installed to $INSTALL_PREFIX/include, documentation and build system files to $INSTALL_PREFIX/share and libraries to $INSTALL_PREFIX/lib. With INSTALL_PREFIX set, RPATH will be enabled. To disable RPATH (for example, if $INSTALL_PREFIX/$INSTALL_LIB is already a system-known location for shared libraries), set the make macro install_rpath to 0 by adding install_rpath=0 to platform_macros.GNU.
Issue here:
In the MSYS shell, change to the $ACE_ROOT/ace directory and run make:
% cd $ACE_ROOT/ace
% make
Now I noticed that there is no MakeFile in ACE_ROOT/ace which is C:\mingw64\Other\ACE_wrappers\ace
I downloaded my ACE stuff from here.
Any suggestions on what I might be doing wrong ? did I download something wrong ?
You seem to have downloaded the source only distribution, please download the full package, that includes also the GNU makefiles, see http://download.dre.vanderbilt.edu/
ACE comes in the full version with GNUmakefile-s,
In MSYS you give make -f GNUmakefile
EDIT 1
Though building 64-bit binaries is supported for numerous platforms and compilers, the ACE team did not provide it for MINGW. There is something to do ...
EDIT 2
Following script should do the configuration for 64-bit binaries in MingW-64
#! /bin/bash
#
# Configure ACE/TAO for 32/64 bit build with MINGW64
#
# Precondition:
# This script is located in the parent folder of ACE_Wrappers
# File access permissions in ACE_Wrappers allow editing of files (sed):
# Easyest, delivered full ACE/TAO ZIP was extracted using Windows Explorer.
# When extracting with 7z, it will correctly preserve access rights and
# they need to be granted for the user, explicitly
#
# Postcondition:
# ACE is configured for MINGW build
# Script is involutoric
#
# Author: Sam Ginrich
# No warranty of any kind!
#
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#
#
# Definition of Setup parameters
# these are entered into configuration files, if not already there, never modified!
#
#
#buildbits= # does nothing
#buildbits=32 # configure 32-bit build
#buildbits=64 # configure 64-bit build
buildbits=64
#winsock2=0 # configure parameter to exclude winsock2 library
#winsock2=1 # configure parameter to include winsock2 library
#winsock2= # does nothing, same effect as winsock2=1
winsock2=
# Issue with header "$ACE_ROOT/ace/OS_NS_stdlib.h"
# In some MINGW installation, the compiler is confused with a defined 'rand_r' macro
# This takes effect when building TAO, not ACE
#
#rand_r_issue= # does nothing, suggested initial value
#rand_r_issue=1 # modifies "$ACE_ROOT/ace/OS_NS_stdlib.h" to #undef-ine macro 'rand_r',
# before impact, suggested when issue occurs
rand_r_issue=
#
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
echo "ACE/TAO Build Target Values"
echo ""
echo "buildbits=$buildbits"
echo "winsock2=$winsock2"
echo "rand_r_issue=$rand_r_issue"
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
echo ""
echo "STEP: Enter ACE_Wrappers and define locations"
cd ./ACE_Wrappers
# Check, whether we arrives there ...
if [ ! -f "./ACE-INSTALL.html" ]; then
echo "ACE_Wrappers missing or invalid ... STOP"
exit 1
fi
export ACE_ROOT=${PWD}
export TAO_ROOT=${ACE_ROOT}/TAO
# Set C-Config Header for Windows
echo '#include "ace/config-win32.h"' > ace/config.h
# Set Platform MINGW
pl_macro=$ACE_ROOT/include/makeinclude/platform_macros.GNU
pl_mingw='$(ACE_ROOT)/include/makeinclude/platform_mingw32.GNU'
echo "include $pl_mingw" > $pl_macro
if [ "$buildbits" != "" ];
then
echo "------------------------------------------------------------"
echo ""
echo "STEP: Provide support for 64-bit build in 'platform_g++_common.GNU'"
pl_gpp=$ACE_ROOT/include/makeinclude/platform_g++_common.GNU
donetag2=" FLAGS_C_CC += -m64"
marker2="CCFLAGS += -Wnon-virtual-dtor"
buildbitsSwitch="ifeq (\$(buildbits),32)\n FLAGS_C_CC += -m32\n LDFLAGS += -m32\nendif\nifeq (\$(buildbits),64)\n FLAGS_C_CC += -m64\n LDFLAGS += -m64\nendif"
case `grep -Fx "$donetag2" "$pl_gpp" >/dev/null; echo $?` in
0)
echo "File $pl_gpp already modified "
;;
1)
# anyway store a copy
cp $pl_gpp /tmp
echo "copy of original $pl_gpp stored in \\tmp"
echo "insert compiler switches for buildbits rule"
sed -i "s/$marker2/$marker2\n\n$buildbitsSwitch/g" $pl_gpp
;;
*)
echo "Error scanning file $pl_gpp"
;;
esac
echo "------------------------------------------------------------"
echo ""
pl_mingw=$ACE_ROOT/include/makeinclude/platform_mingw32.GNU
echo "STEP: Set parameter for 64-bit build in $pl_mingw"
donetag3="buildbits =.*"
marker3="mingw32 = 1"
buildbitsDef="# 32\/64-bit build\n# parameter 'buildbits' is applied in platform_gnuwin32_common.GNU\nbuildbits = $buildbits"
case `grep -Ex "$donetag3" "$pl_mingw" >/dev/null; echo $?` in
0)
echo "File $pl_mingw already modified "
echo "Verify value! "
grep "buildbits =" $pl_mingw
;;
1)
# anyway store a copy
cp $pl_mingw /tmp
echo "copy of original $pl_mingw stored in \\tmp"
echo "insert buildbits=$buildbits"
sed -i "s/$marker3/$marker3\n\n$buildbitsDef/g" $pl_mingw
;;
*)
echo "Error scanning file $pl_mingw"
;;
esac
fi
if [ "$winsock2" != "" ];
then
echo "------------------------------------------------------------"
echo ""
#pl_mingw=$ACE_ROOT/include/makeinclude/platform_mingw32.GNU
echo "STEP: Winsock lack control"
donetag4="winsock2 =.*"
marker4=$marker3
winsockDef="winsock2 = $winsock2"
# $donetag4 is regular expression, -E
case `grep -Ex "$donetag4" "$pl_mingw" >/dev/null; echo $?` in
0)
echo "File $pl_mingw already modified "
echo Verify Value!
grep "winsock2 =" $pl_mingw
;;
1)
# anyway store a copy
cp $pl_mingw /tmp
echo "copy of original $pl_mingw stored in \\tmp"
echo insert $winsockDef
sed -i "s/$marker4/$marker4\n\n$winsockDef/g" $pl_mingw
;;
*)
echo "Error scanning file $pl_mingw"
;;
esac
fi
if [ "$rand_r_issue" == "1" ];
then
echo "------------------------------------------------------------"
echo ""
echo "STEP: Handle issue with defined C-macro rand_r"
onsll=$ACE_ROOT/ace/OS_NS_stdlib.h
donetag1="//#rand_undefined"
case `grep -Fx "$donetag1" "$onsll" >/dev/null; echo $?` in
0)
echo "File $onsll already modified"
;;
1)
# anyway store a copy
cp $onsll /tmp
echo "copy of original $pl_gpp stored in \\tmp"
echo "insert '#undef rand_r'"
sed -i 's/#if !defined (ACE_LACKS_RAND_R)/\/\/#rand_undefined\n#undef rand_r\n#if !defined (ACE_LACKS_RAND_R)/g' $onsll
;;
*)
echo "Error scanning file $onsll"
;;
esac
fi
echo "============================================================"
echo ""
echo "Content of "$ACE_ROOT/ace/config.h" is"
cat "ace/config.h"
echo ""
echo Content of "$pl_macro" is
cat $pl_macro
echo "-------------------------------------------------------------"
echo ""
echo ""
echo ""
echo "Suggested BUILD STEPS:"
echo ""
echo ""
echo "# 1. Define context"
echo "export ACE_ROOT=${PWD}"
echo "export TAO_ROOT=${ACE_ROOT}/TAO"
echo ""
echo "# 2. Build ACE"
echo 'cd ${ACE_ROOT}/ace'
echo "make -f GNUmakefile"
echo ""
echo "# 3. Verify ACE"
echo 'cd ${ACE_ROOT}/tests'
echo "make -f GNUmakefile"
echo "perl run_test.pl"
echo "#NOTE: Windows Firewall will ask for permission for each upcoming server instance"
echo ""
echo "# 4. Build TAO"
echo 'cd ${TAO_ROOT}'
echo "make -f GNUmakefile"
echo ""
echo "# 5. Basic TAO verification"
echo 'cd ${TAO_ROOT}/tests'
echo "make -f GNUmakefile"
echo 'cd ${TAO_ROOT}/tests/Param_Test'
echo "perl run_test.pl"
we have a C++ project in which we need to redirect the standard output to a text file using the following script:
#!/bin/bash
echo "Descend into 'workdirectory' directory"
cd workdirectory
#
for item in *
do
echo " "
echo "EXECUTING" $item
cd $item
Aprog >zoutput02.txt
cd ..
echo "EXECUTION COMPLETE"
done
echo "Return from 'testdirectory' directory"
cd ..
echo " "
When I try to run this script using bash ./scriptname.txt, it returns:
EXECUTING work
./scriptname.txt: line 10: Aprog: command not found
EXECUTION COMPLETE
Return from 'workdirectory' directory
What does this error mean?
Thanks!
You are CD ing around. Aprog is almost certainly not on your path.
Either add Aprog to your PATH or define it in the script.
aprog=/path/to/aprog
$aprog > zoutput02.txt