xargs 的默认分隔符可以更改吗?



我想要以下行为,而不必使用选项显式指定它:

xargs -d 'n'

与大多数命令不同,您不能只使用别名,因为管道无法识别别名(作为旁注,为什么它是这样设计的?我也尝试创建自己的~/bin/xargs脚本,但我认为这并不像将"$@"作为脚本中的字符串阅读那么简单。

任何建议如何使分隔符默认为换行符?当我在路径中有空格时,我不想收到一堆错误(并且使用 find ... -print0 | xargs -0 会产生其他不良影响(。

更新

我的 shell 脚本尝试是这样的:

/usr/local/bin/xargs -d 'n' "$@"

我在命令行上测试了xargs -d 'n' -n1 echo,它像宣传的那样工作;将输入分解为单行并回显它。

您可能会被变量赋值期间有关 shell 转义的假设所困扰。 例如,如果你的 shell 脚本类似于这样:

CMD="xargs -d '' -n1 echo"
猫输入文件 |$CMD

然后发生错误,因为整个 CMD 字符串周围的双引号保留分隔符中的单引号和反斜杠。

如果要将 xargs 命令括在引号内,则可以将其更改为以下内容(不要使用单引号(

CMD="xargs -d -n1 echo"
猫输入文件 |$CMD

它可能会根据您的需要运行。

在 CentOS 6.4, xargs 版本 4.4.2 上测试

如果你的 xargs 版本不支持设置不同的分隔符 (比如 2011 FreeBSD 服务器上的分隔符...(, 你可以使用 tr 把你的分隔符变成xargs可以使用的东西。如果您的输入包含您的xargs认为分隔符的字符(例如空格(,您可能需要在前后使用一些翻译,或者您可以简单地将分隔符转换为 NULL/0x0并将-0参数传递给 xargs

下面是一个使用 xargs 查找$PATH中可能使用 shell 的任何文件的示例(我在这里的原因,然后我想出了另一个答案(:
echo $PATH | tr ':' '' | xargs -0 ls | grep sh | sort

我在我的PATH~/bin,并保留了一个简短的脚本,其中包含我最喜欢的默认值,我系统上的所有shell都可以访问(在不同时间我使用Dash,Bash和Fish(。它很小:

#!/usr/bin/env sh
exec xargs -rd\n "$@"

调用该脚本x以避免与需要标准xargs默认值的脚本发生冲突。如果您尝试替换xargs本身(我不建议这样做(,请确保您的~/bin在 PATH 中显示的位置高于系统xargswhich -a xargs告诉我,系统中唯一的xargs存在于/usr/bin/xargs,所以我知道我的主目录 /home/stephen/bin 必须像这样出现在它前面:

$ echo "$PATH"
/home/stephen/bin:...:/usr/bin:...

无论哪种方式,作为所有程序都可以访问的脚本,这意味着您可以执行诸如 find|x grepsh -c 'x ...' .

如果您使用 Bash 并且更喜欢别名,您也可以只使用:

alias x=xargs -rd\n # n delim, don't run on empty in, + alias expansion

请注意别名扩展的尾随空格。这使您可以链接别名。例如,如果除了上述别名之外,我还有一个名为 g 的 grep 别名,则以下内容将起作用:

# extended regex, skip binaries, devices, sockets, & dirs, colored, & line
# -buffered. use a non-canonical alias instead of GREP_OPTIONS which may wreck
# assuming scripts
alias g='grep -EID skip -d skip --color=auto --line-buffered'
$ find|x g foo

x/xargs脚本方法本身无法有效地做到这一点。

由于我在 shell 之间切换并且主要使用一台 PC,因此我将我需要的少数别名保留为~/bin中的单独脚本和帮助程序脚本中的 shell 不可知别名,~/.sh_aliases (由 ~/.shrc~/.bashrc~/.config/fish/config.fish 提供,因为它们都支持类似 Bash 的别名语法。如果我经常在多台PC上工作,我可能会尝试将它们合并到~/.bashrc中。

最新更新