6

There is no read applet comming with busy box.

Is there any way to read a txt file line by line using busybox?

What I have now is

while read line
do
     echo $line
done < "$InputFile"
limovala
  • 734
  • 3
  • 9
  • 22
  • 1
    That doesn't work? Busybox uses `ash` for a shell, which is not POSIX complaint, but still includes a POSIX `read`. – jordanm Aug 19 '13 at 05:51
  • 2
    See also [Understanding IFS](http://unix.stackexchange.com/questions/26784/understanding-ifs), [Why is `while IFS= read` used so often, instead of `IFS=; while read..`?](http://unix.stackexchange.com/questions/18886/why-is-while-ifs-read-used-so-often-instead-of-ifs-while-read), [In `while IFS= read..`, why does IFS have no effect?](http://unix.stackexchange.com/questions/18922/in-while-ifs-read-why-does-ifs-have-no-effect), … – Gilles 'SO- stop being evil' Aug 19 '13 at 23:32

2 Answers2

17

read is a shell builtin (it couldn't set a shell variable if it were not).

So, if your busybox sh is based on ash, it's:

while IFS= read -r line <&3; do
  printf '%s\n' "$line"
done 3< "$InputFile"

Like in any POSIX shell. But like with any shell, using while read loops to process text is generally bad shell scripting practice.

Above, you need:

  • IFS= otherwise leading and trailing unescaped spaces and tabs are stripped from the lines
  • -r, otherwise backslashes are treated as an escape character and removed (unless escaped)
  • printf, not echo which wouldn't work for lines that are for instance -nene
  • "$line" quoted (not $line) otherwise the content of the line is split on spaces and tabs, and globbing patterns expanded.
  • <&3 and 3< ..., if you need access to the original stdin within the loop.

If the file contains characters after the last line and you want to display them, you can add after the loop:

[ -z "$line" ] || printf %s "$line"

Note that that loop cannot handle binary data (the NUL character).

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • This looks like unnecessary complexity to what should be a working example from the OP. – jordanm Aug 19 '13 at 05:53
  • 2
    @jordanm, I've edited the answer to give reasons for the added complexity. – Stéphane Chazelas Aug 19 '13 at 06:16
  • Maybe it could be better with `while IFS= read -r line <&3 || [ -n "$line" ] ; do` to avoid repeating the internals of the loop on non-null last line. Yes, it still will not handle a NUL character. –  Jan 18 '16 at 21:35
-1

I managed to solve my requirement by using

head testInputs/test1 -n $getLineNum | tail -n 1

getLineNum increments on each while loop.

but it is not the exact answer for my question.

Also you need to add some thing like #EOF at the last line and search for it to break the loop.

limovala
  • 734
  • 3
  • 9
  • 22
  • Why do you need to prefix `busybox` to every command? Are you not entering that command line in `busybox` shell? Does that shell not have a `read` builtin? (what does `type read` tell you there?). – Stéphane Chazelas Aug 19 '13 at 08:50
  • @StephaneChazelas I am writing this script for an embedded device, so to make sure the busybox applet is called instead of the actual command, I use busybox prefix I am using Bourne shell '/bin/sh' – limovala Aug 19 '13 at 09:32
  • 4
    But by doing so you end up using it differently from what your embedded device would (you don't want to call utilities like that as that means reexecuting busybox for every command which is a waste since nowadays busybox can call utilities without reexecuting itself). `busybox` will call its own commands in priority. If you don't want to call utilities from `/bin` or `/usr/bin`, remove those directories from `$PATH`. – Stéphane Chazelas Aug 19 '13 at 09:41
  • @StephaneChazelas thanks, I will Update my scripts – limovala Aug 19 '13 at 09:57