如何使用文件的行作为命令的参数?

Yoo*_*Yoo 132 unix linux shell command-line command-line-arguments

说,我有一个foo.txt指定N参数的文件

arg1
arg2
...
argN
Run Code Online (Sandbox Code Playgroud)

我需要传递给命令 my_command

如何使用文件的行作为命令的参数?

gle*_*man 209

如果你的shell是bash(以及其他),那么$(cat afile)是一个快捷方式$(< afile),所以你要写:

mycommand "$(< file.txt)"
Run Code Online (Sandbox Code Playgroud)

在"命令替换"部分的bash手册页中记录.

另外,让你的命令从stdin读取,所以: mycommand < file.txt

  • 要迂腐,使用`<`运算符不是捷径.这意味着shell本身将执行重定向,而不是为它的重定向属性执行`cat`二进制. (10认同)
  • 除非我丢失引号,否则它对我不起作用。使用引号,它将整个文件作为 1 个参数。如果没有引号,它将每一行解释为一个单独的参数。 (5认同)
  • 这是一个内核设置,因此您需要重新编译内核.或者调查xargs命令 (2认同)
  • @ykaner,因为如果没有`“ $(…)”`,file.txt`的内容将被传递给`mycommand`的标准输入,而不是作为参数。`“ $(…)”`表示_run命令并以string_形式返回输出;在这里,“命令”仅读取文件,但是可能更复杂。 (2认同)

Wil*_*ill 35

如前所述,您可以使用反引号或$(cat filename).

没有提到的,我认为值得注意的是,你必须记住,shell会根据空格拆分该文件的内容,将它找到的每个"单词"作为参数发送给你的命令.虽然您可以将命令行参数括在引号中,以便它可以包含空格,转义序列等,但从文件中读取将不会执行相同的操作.例如,如果您的文件包含:

a "b c" d
Run Code Online (Sandbox Code Playgroud)

你将得到的论据是:

a
"b
c"
d
Run Code Online (Sandbox Code Playgroud)

如果要将每一行作为参数拉出,请使用while/read/do构造:

while read i ; do command_name $i ; done < filename
Run Code Online (Sandbox Code Playgroud)


Wes*_*ice 15

command `< file`
Run Code Online (Sandbox Code Playgroud)

将文件内容传递给stdin上的命令,但会删除换行符,这意味着你不能单独迭代每一行.为此你可以用'for'循环编写一个脚本:

for i in `cat input_file`; do some_command $i; done
Run Code Online (Sandbox Code Playgroud)

  • (支持这个的人真的测试过吗?```command`&lt;file```` **在bash或POSIX sh中都不起作用; zsh是另一回事,但这不是shell这个问题即将)。 (3认同)

小智 14

你使用反引号来做到这一点:

echo World > file.txt
echo Hello `cat file.txt`
Run Code Online (Sandbox Code Playgroud)

  • 这不会创建* an *参数-因为它不加引号,所以会进行字符串拆分,因此,如果在第一步中发出`echo“ Hello * Starry * World”&gt; file.txt`, d至少将四个单独的参数传递给第二个命令-而且可能更多,因为`*`会扩展为当前目录中存在的文件名。 (3认同)
  • ...并且由于它正在运行glob扩展,因此它不会“确切地”释放文件中的内容。**并且**,因为它正在执行命令替换操作,所以效率极低-实际上,它是`fork()`断开子容器,并在其stdout上附加了FIFO,然后作为其子级调用`/ bin / cat`。子外壳,然后通过FIFO读取输出;与`$(&lt;file.txt)`相比,后者直接将文件内容读入bash中,而没有涉及子shell或FIFO。 (2认同)

Cha*_*ffy 8

如果你想以一种强大的方式做到这一点,它适用于每个可能的命令行参数(带空格的值,带换行符的值,带有文字引号的值,不可打印的值,带有glob字符的值等),它会得到一些更有趣的.


要给出一个参数数组,要写入文件:

printf '%s\0' "${arguments[@]}" >file
Run Code Online (Sandbox Code Playgroud)

......与替换"argument one","argument two"等适当的.


要从该文件中读取并使用其内容(在bash,ksh93或其他带有数组的shell中):

declare -a args=()
while IFS='' read -r -d '' item; do
  args+=( "$item" )
done <file
run_your_command "${args[@]}"
Run Code Online (Sandbox Code Playgroud)

从该文件读取并使用其内容(在没有数组的shell中;请注意,这将覆盖您的本地命令行参数列表,因此最好在函数内部完成,这样您就会覆盖函数的参数而不是全球清单):

set --
while IFS='' read -r -d '' item; do
  set -- "$@" "$item"
done <file
run_your_command "$@"
Run Code Online (Sandbox Code Playgroud)

请注意-d(允许使用不同的行尾分隔符)是非POSIX扩展,而没有数组的shell也可能不支持它.如果是这种情况,您可能需要使用非shell语言将NUL分隔的内容转换为eval-safe形式:

quoted_list() {
  ## Works with either Python 2.x or 3.x
  python -c '
import sys, pipes, shlex
quote = pipes.quote if hasattr(pipes, "quote") else shlex.quote
print(" ".join([quote(s) for s in sys.stdin.read().split("\0")][:-1]))
  '
}

eval "set -- $(quoted_list <file)"
run_your_command "$@"
Run Code Online (Sandbox Code Playgroud)


Phi*_*ilT 7

所有答案似乎都不适合我或太复杂。幸运的是,它并不复杂xargs(在 Ubuntu 20.04 上测试)。

正如OP提到的那样,这适用于文件中单独一行上的每个参数,这也是我所需要的。

cat foo.txt | xargs my_command
Run Code Online (Sandbox Code Playgroud)

需要注意的一件事是它似乎不适用于别名命令。

如果命令接受字符串中包含的多个参数,则接受的答案有效。在我使用 (Neo)Vim 的情况下,它不会,并且参数都粘在一起。

xargs它做得正确并且实际上为您提供了提供给命令的单独参数。


cho*_*ovy 6

这是我将文件内容作为参数传递给命令的方式:

./foo --bar "$(cat ./bar.txt)"
Run Code Online (Sandbox Code Playgroud)


Cob*_*ast 6

如果您需要做的就是将文件转换arguments.txt为内容

arg1
arg2
argN
Run Code Online (Sandbox Code Playgroud)

进入my_command arg1 arg2 argN然后你可以简单地使用xargs

xargs -a arguments.txt my_command
Run Code Online (Sandbox Code Playgroud)

您可以在xargs调用中添加额外的静态参数,例如xargs -a arguments.txt my_command staticArgwhich will callmy_command staticArg arg1 arg2 argN