有些命令不支持輸入流
前面我們講過,有些命令是不支持輸入流的,只支持命令列引數,如最常用的 ls,我們通常這樣使用
$ ls /var/
backups cache crash lib local lock log mail metrics opt run snap spool tmp
但是不能這樣使用
$ echo "/var" | ls
這樣使用的話,ls 會忽略管道傳遞給它的輸入流,最終相當于,僅僅運行了不帶引數的 ls,
xargs 的用處
那么,如果命令列或腳本確實需要用到類似的寫法,有什么解決辦法呢?答案就是用 xargs,xargs 的其中一個作用就是可以將管道或標準輸入的資料轉換成命令列引數,例如
$ echo "/var" | xargs ls
backups cache crash lib local lock log mail metrics opt run snap spool tmp
以上,加了一個 xargs ,就可以將管道的輸出轉換成 ls 的引數,
原理分析
管道本來的作用是連接 echo 的標準輸出到 ls 的標準輸入,加了 xargs,就相當于管道連接了 echo 的標準輸出到 xargs 的標準輸入,xargs 又將其標準輸入的內容轉換成命令的引數,傳遞給命令,
原始碼分析
先上原始碼
xargs.c
# define READ_ARGS(l, e, nmc, mc) process_stdin(l, e, nmc, mc)
int xargs_main(int argc, char **argv)
{
while ((list = READ_ARGS(list, eof_str, n_max_chars, max_chars)) != NULL || /* 從標準輸入讀取資料作為引數串列 */
(opt & OPT_NO_EMPTY) == 0)
{
opt |= OPT_NO_EMPTY;
n = 0;
n_chars = 0;
/* allocating pointers for execvp:
a*arg, n*arg from stdin, NULL */
args = xcalloc(n + a + 1, sizeof(char *));
/* Store the command to be executed
(taken from the command line) */
for (i = 0; i < a; i++)
args[i] = argv[i];
/* (taken from stdin) */
for (cur = list; n; cur = cur->link) {
args[i++] = cur->data;
n--;
}
if ((opt & OPT_INTERACTIVE) == 0 || xargs_ask_confirmation() != 0) {
child_error = xargs_exec(args); /* 執行命令,其中 args 的值可能為: args[0] = "ls", args[1] = "-a" */
}
/* clean up */
for (i = a; args[i]; i++) {
cur = list;
list = list->link;
free(cur);
}
free(args);
if (child_error > 0 && child_error != 123) {
break;
}
}
return child_error;
}
所以,xargs 的原理就是讀取標準輸入,轉成引數串列,借助 exec 函式,執行命令和引數,
提升
我們發現,通過 xargs 執行的 ls 命令,失去了顏色,那是因為在 shell 中執行的 ls,實際上執行的是 ls --color=auto,ls 是 alias 給 ls --color=auto 起的別名,要想我們的輸出帶顏色,可以使用如下命令:

吶,顏色回來了
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/286735.html
標籤:其他
