我想要以下行为,而不必使用选项显式指定它:
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 中显示的位置高于系统xargs
。 which -a xargs
告诉我,系统中唯一的xargs
存在于/usr/bin/xargs
,所以我知道我的主目录 /home/stephen/bin
必须像这样出现在它前面:
$ echo "$PATH"
/home/stephen/bin:...:/usr/bin:...
无论哪种方式,作为所有程序都可以访问的脚本,这意味着您可以执行诸如 find|x grep
和 sh -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
中。