If you want that last 10 lines:
tail myFile.txt | tr '\n' '\0' | xargs -r0i myCmd {} arg1 arg2
But with GNU xargs
, you can also set the delimiter to newline with:
tail myFile.txt | xargs -ri -d '\n' myCmd {} arg1 arg2
(-0
is short for -d '\0'
).
Portably, you can also simply escape every character:
tail myFile.txt | sed 's/./\\&/g' | xargs -I{} myCmd {} arg1 arg2
Or quote each line:
tail myFile.txt | sed 's/"/"\\""/g;s/.*/"&"/' | xargs -I{} myCmd {} arg1 arg2
If you want the 10 last NUL-delimited records of myFile.txt
(but then that wouldn't be a text file), you'd have to convert the \n
to \0
before calling tail
which would mean the file will have to be read fully:
tr '\n\0' '\0\n' < myFile.txt |
tail |
tr '\n\0' '\0\n' |
xargs -r0i myCmd {} arg1 arg2
Edit (since you changed the tail
to tail -f
in your question):
The last one above obviously doesn't make sense for tail -f
.
The xargs -d '\n'
one will work, but for the other ones, you'll have a buffering problem. In:
tail -f myFile.txt | tr '\n' '\0' | xargs -r0i myCmd {} arg1 arg2
tr
buffers its output when it doesn't go to a terminal (here, a pipe). I.E., it will not write anything until it has accumulated a buffer full (something like 8kiB) of data to write. Which means myCmd
will be called in batches.
On a GNU or FreeBSD system, you can alter the buffering behavior of tr
with the stdbuf
command:
tail -f myFile.txt | stdbuf -o0 tr '\n' '\0' |
xargs -r0i myCmd {} arg1 arg2