0

Suppose I have the following process to write a number + single quote to the file /tmp/test every second:

for i in {1..1000} ; do echo $i\' ; sleep 1 ; done > /tmp/test

I then want to use tail -f and run this through another function. For testing purposes, I'm using echo:

tail -f /tmp/test | xargs echo

This give me the following error (running this without a quote in the input works fine):

xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option

If I add sed to the equation, I don't get any output at all:

tail -f /tmp/test | sed "s/['\"]//g" | xargs echo

Any ideas why I get no output after adding sed, or another way how I can strip the quotes from the input before it gets to xargs?

6
  • 1
    And what arguments would you like be passed to echo? Each blank-delimited word in the input (quotes not special, how about backslash?)? Or the full content of each line? Commented Jul 5, 2020 at 8:39
  • My actual xargs command is xargs -0 -n1 -d '\n' -I {} bash -c 'log -e "$@"' _ {} which seems to be working now after adding the -d parameter
    – Subbeh
    Commented Jul 5, 2020 at 8:46
  • -0, -n1 (or -I) and bash are superfluous here. xargs -rd '\n' -n1 log -e Commented Jul 5, 2020 at 10:54
  • unfortunately not, log is a function that is otherwise not recognized, try yourself: log() { echo $1; } ; export -f log ; echo test| xargs -rd '\n' -n1 log
    – Subbeh
    Commented Jul 5, 2020 at 10:57
  • 1
    Oh exported bash function I take it. Then xargs -rd '\n' -n1 bash -c 'log "$@"' bash (avoid _ for $0). But instead of running one bash per line, you may want to use a while IFS= read -r line loop within one bash instance and do away with xargs. Commented Jul 5, 2020 at 10:58

2 Answers 2

1

There's a number of things.

First: "tail -f" will never finish, so "xargs" will likewise remain running indefinitely. You can open a second window to "kill -HUP" the "tail -f" process to make both the "tail -f" and "xargs" finish, and thus produce output.

Second: "xargs" is buffering the input, and not getting what it considers to be a "full buffer", so by the time the 1000 second marks have been output, it hasn't yet run the echo command even once. If you'd like "xargs" to run the echo separately for each input row, you'd need to add "-n 1" option to xargs.

As for "xargs" not liking the single quote marks, you could use option "-d '\n'" to disable the quote processing and only separate the input arguments by a newline.

1
  • Thanks! Adding '\n' solved the issue
    – Subbeh
    Commented Jul 5, 2020 at 8:45
1

Maybe

tail -f /tmp/test | sed "s/['\"]//g" | while read line; do
  do_something "$line"
done

And check this: https://stackoverflow.com/questions/199266/make-xargs-execute-the-command-once-for-each-line-of-input

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .