What is the equivalent to xargs -r under OsX

2019-06-17 06:28发布

Are they any equivalent under OSX to the xargs -r under Linux ? I'm trying to find a way to interupt a pipe if there's no data.

For instance imagine you do the following:

touch test
cat test | xargs -r echo "content: "

That doesn't yield any result because xargs interrupts the pipe.

Is there either some hidden xargs option or something else to achieve the same result under OSX?

标签: macos bash shell
5条回答
放荡不羁爱自由
2楼-- · 2019-06-17 06:54

The POSIX standard for xargs mandates that the command be executed once, even if there are no arguments. This is a nuisance, which is why GNU xargs has the -r option. Unfortunately, neither BSD (MacOS X) nor the other mainstream Unix versions (AIX, HP-UX, Solaris) support it.

If it is crucial to you, obtain and install GNU xargs somewhere that your environment will find it, without affecting the system (so don't replace /usr/bin/xargs unless you're a braver man than I am — but /usr/local/bin/xargs might be OK, or $HOME/bin/xargs, or …).

查看更多
倾城 Initia
3楼-- · 2019-06-17 07:05

Here's a quick and dirty xargs-r using a temporary file.

#!/bin/sh
t=$(mktemp -t xargsrXXXXXXXXX) || exit
trap 'rm -f $t' EXIT HUP INT TERM
cat >"$t"
test -s "$t" || exit
exec xargs "$@" <"$t"
查看更多
三岁会撩人
4楼-- · 2019-06-17 07:06

There is no standard way to determine if the xargs you are running is GNU or not. I set $gnuargs to either "true" or "false" and then have a function that replaces xargs and does the right thing.

On Linux, FreeBSD and MacOS this script works for me. The POSIX standard for xargs mandates that the command be executed once, even if there are no arguments. FreeBSD and MacOS X violate this rule, thus don't need "-r". GNU finds it annoying, and adds -r. This script does the right thing and can be enhanced if you find a version of Unix that does it some other way.

#!/bin/bash

gnuxargs=$(xargs --version 2>&1 |grep -s GNU >/dev/null && echo true || echo false)

function portable_xargs_r() {
  if $gnuxargs ; then
    cat - | xargs -r """$@"""
  else
    cat - | xargs """$@"""
  fi
}

echo 'this' > foo
echo '=== Expect one line'
cat foo | portable_xargs_r echo "content: "
echo '=== DONE.'

cat </dev/null > foo
echo '=== Expect zero lines'
cat foo | portable_xargs_r echo "content: "
echo '=== DONE.'
查看更多
聊天终结者
5楼-- · 2019-06-17 07:08

You can use test or [:

if [ -s test ] ; then cat test | xargs echo content: ; fi
查看更多
smile是对你的礼貌
6楼-- · 2019-06-17 07:12

You could make sure that the input always has at least one line. This may not always be possible, but you'd be surprised how many creative ways this can be done.

查看更多
登录 后发表回答