If you really want to do it in bash, I'd suggest making use of the -u fd
option to read from the two files simultaneously using numbered streams, e.g.
while read -r -u3 product; read -r -u4 comp; do
printf '%s;%s\n' "$product" "$comp"
done 3<products.txt 4<comps.txt
However, you could just use the paste
utility
paste -d\; products.txt comps.txt
You often see this in case of utilities like busybox
, a program that can provide most of the common unix utilities in one executable, that behaves different depending on its invocation/ busybox
can do a whole lot of functions, acpid
through zcat
.
And it commonly decides what it's supposed to be doing by looking at it's argv[0]
parameter to main()
. And that shouldn't be a simple comparison. Because argv[0]
might be something like sleep
, or it might be /bin/sleep
and it should decide to do the same thing. In other words, the path is going to make things more complex.
So if things were done by the worker program right, your logging wrapper could execute from something like /bin/realstuff/make_tea
and if the worker looks at argv[0]
basename only, then the right function should execute.
#!/bin/sh -
myexec=/tmp/MYEXEC$$
mybase=`basename -- "$0"`
echo "$0 $@" >> logfile
mkdir "$myexec" || exit
ln -fs /usr/bin/real/do_stuff "$myexec/$mybase" || exit
"$myexec/$mybase" "$@"
ret=$?
rm -rf "$myexec"
exit "$ret"
In the example above, argv[0]
should read something like /tmp/MYEXEC4321/make_tea
(if 4321 was the PID for the /bin/sh
that ran)which should trigger the basename make_tea
behavior
If you want argv[0]
to be an exact copy of what it would be without the wrapper, you have a tougher problem. Because of absolute file paths beginning with /
. You can't make a new /bin/sleep
(absent chroot
and I don't think you want to go there). As you note, you could do that with some flavor of exec()
, but it wouldn't be a shell wrapper.
Have you considered using an alias to hit the logger and then start the base program instead of a script wrapper? It'd only catch a limited set of events, but maybe those are the only events you care about
Best Answer
That runs the loop until one of the files is exhausted. Replace the
&&
s with||
s to run it until all the files are exhausted instead (using empty arguments for shorter files).With GNU
xargs
, you could also do:(though beware
./program
's stdin would then be/dev/null
)