它们在OSX下是否与Linux下的xargs -r
相当?如果没有数据,我正试图找到一种方法来中断管道。
例如,假设您执行以下操作:
touch test
cat test | xargs -r echo "content: "
这不会产生任何结果,因为xargs会中断管道。
是否有一些隐藏 xargs选项或其他东西在OSX下实现相同的结果?
答案 0 :(得分:2)
您可以使用test
或[
:
if [ -s test ] ; then cat test | xargs echo content: ; fi
答案 1 :(得分:2)
xargs
的POSIX标准要求命令执行一次,即使没有参数。这是一个令人讨厌的问题,这就是GNU xargs
具有-r
选项的原因。不幸的是,BSD(MacOS X)和其他主流Unix版本(AIX,HP-UX,Solaris)都不支持它。
如果对您至关重要,请在您的环境找到的地方获取并安装GNU xargs
,而不会影响系统(因此,除非您是勇敢的人,否则不要替换/usr/bin/xargs
我是 - 但/usr/local/bin/xargs
可能没问题,或$HOME/bin/xargs
或......)。
答案 2 :(得分:2)
没有标准方法可以确定您运行的xargs是否为GNU。我将$gnuargs
设置为“true”或“false”,然后使用一个替换xargs并执行正确操作的函数。
在Linux,FreeBSD和MacOS上,这个脚本适合我。 xargs的POSIX标准要求命令执行一次,即使没有参数。 FreeBSD和MacOS X违反了这条规则,因此不需要“-r”。 GNU发现它很烦人,并添加了-r
。这个脚本是正确的,如果你找到一个以其他方式做它的Unix版本,可以增强它。
#!/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.'
答案 3 :(得分:1)
使用POSIX xargs
¹,为避免在输入为空时运行the-command
,可以使用moreutils
的{{1}}(对于,如果不为空< / em>):
ifne
或使用... | ifne xargs ... the-command ...
包装器检查参数数量:
sh
¹,尽管几乎不使用... | xargs ... sh -c '[ "$#" -eq 0 ] || exec the-command ... "$@"' sh
,因为它不支持xargs
,当输入为非文本时(例如,在大多数系统上不是这样的文件名),具有不确定的行为保证是POSIX语言环境以外的文本),以一种非常神秘的方式解析其输入,并且取决于语言环境,并且如果任何单词的长度超过255个字节,则不做任何保证!
答案 4 :(得分:0)
您可以确保输入始终至少有一行。这可能并不总是可行的,但你会惊讶地发现有多少创造性的方法可以做到。
答案 5 :(得分:0)
这是一个使用临时文件的快速而脏的xargs-r
。
#!/bin/sh
t=$(mktemp -t xargsrXXXXXXXXX) || exit
trap 'rm -f $t' EXIT HUP INT TERM
cat >"$t"
test -s "$t" || exit
exec xargs "$@" <"$t"
答案 6 :(得分:0)
一个典型的用例如下:
find . -print0 | xargs -r -0 grep PATTERN
某些版本的xargs没有-r
标志。在这种情况下,您可以提供/ dev / null作为第一个文件名,以便grep永远不会收到文件名的空列表。由于永远不会在/ dev / null中找到该模式,因此不会影响输出:
find . -print0 | xargs -0 grep PATTERN /dev/null
答案 7 :(得分:0)
您可以测试流中是否有任何内容:
cat test | { if IFS= read -r tmp; then { printf "%s\n" "$tmp"; cat; } | xargs echo "content: "; fi; }
# ^^^ - otherwise just do nothing
# ^^^^^^^^^^^^^^^^^^^^^^^ - to xargs
# ^^^ - and the rest of input
# ^^^^^^^^^^^^^^^^^^^^^^ - redirect first line
# ^^^^^^^^^^^^^^^^^^^ - try reading anything
# or with a function
# even TODO: add the check of `portable_xargs_r` in the other answer and call `xargs -r` when available.
xargs_r() {
if IFS= read -r tmp; then
{ printf "%s\n" "$tmp"; cat; } | xargs "$@"
fi
}
cat test | xargs_r echo "content: "
此方法在子壳内部的管道内部运行检查,因此可以有效地用于复杂的管道设置中。