比方说,我有一个文件foo.txt
,其中指定了N
个参数。
arg1
arg2
...
argN
我需要将文件的行作为参数传递给命令my_command
,该如何操作?
比方说,我有一个文件foo.txt
,其中指定了N
个参数。
arg1
arg2
...
argN
我需要将文件的行作为参数传递给命令my_command
,该如何操作?
如果你的shell是bash(还有其他一些),$(cat afile)
的一个快捷方式是$(< afile)
,因此你可以写成:
mycommand "$(< file.txt)"
在bash man页面的“Command Substitution”部分有详细说明。
另一种方法是让您的命令从标准输入读取,例如:mycommand < file.txt
<
运算符并不是一个快捷方式。它意味着 shell 本身将执行重定向功能,而不是执行 cat
二进制文件以进行重定向。 - lstyls"$(…)"
,所以file.txt
的内容会被传递到mycommand
的标准输入中,而不是作为一个参数。 "$(…)"
的意思是“运行命令并将输出作为字符串返回”;在这里,“命令”只是读取文件,但也可以更复杂。 - törzsmókus如先前提到的,你可以使用反引号或 $(cat filename)
。
但需要注意的是,shell会按照空格将文件内容分解为多个“单词”,并将每个“单词”作为一个参数传递给您的命令。尽管您可以用引号将命令行参数括起来,以便它可以包含空格、转义序列等,但从文件中读取不会执行同样的操作。例如,如果您的文件包含:
a "b c" d
你将得到的参数是:
a
"b
c"
d
如果您想将每一行作为参数提取出来,请使用while/read/do结构:
while read i ; do command_name $i ; done < filename
command `< file`
这将文件内容传递给命令的标准输入(stdin),但会去除换行符,意味着您无法逐行迭代。为此,您可以编写一个带有“for”循环的脚本:
for line in `cat input_file`; do some_command "$line"; done
或者(多行变量):
for line in `cat input_file`
do
some_command "$line"
done
或者(多行变体使用$()
而不是``
):
for line in $(cat input_file)
do
some_command "$line"
done
< file
意味着它实际上不会对 command
执行重定向。 - Charles Duffycommand `< file`
在 bash 和 POSIX sh 中都 无法工作,虽然 zsh 可以,但这不是本问题所涉及的 shell。 - Charles Duffygit add
来添加一堆待添加的行。 - Gabriel Staplesecho World > file.txt
echo Hello `cat file.txt`
echo "Hello * Starry * World" > file.txt
,则会被视为字符串分割,至少会传递四个单独的参数给第二个命令 - 并且很可能更多,因为星号会扩展成当前目录中存在的文件名。 - Charles Duffy如果你希望以一种健壮的方式来处理每一个可能的命令行参数(包括带有空格、换行符、文字引号字符、不可打印字符、带有通配符等),那就会变得有点有趣。
为了将其写入文件,给定一个参数数组:
printf '%s\0' "${arguments[@]}" >file
用适当的参数(例如"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[@]}"
在没有使用数组的情况下从该文件中读取并使用其内容(请注意,这将覆盖您本地的命令行参数列表,因此最好在函数内部执行此操作,以便您覆盖函数的参数而不是全局列表):
set --
while IFS='' read -r -d '' item; do
set -- "$@" "$item"
done <file
run_your_command "$@"
请注意,-d
(允许使用不同的行尾分隔符)是一种非POSIX扩展,而没有数组的shell也可能不支持它。如果是这种情况,您可能需要使用非shell语言将以NUL为分隔符的内容转换为eval
-安全形式:
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 "$@"
arguments.txt
:arg1
arg2
argN
如果你想将文本转换为 my_command arg1 arg2 argN
的格式,那么你可以使用 xargs
命令:
xargs -a arguments.txt my_command
xargs
调用中添加额外的静态参数,例如xargs -a arguments.txt my_command staticArg
,它将调用my_command staticArg arg1 arg2 argN
。对我来说,所有的答案似乎都不起作用或者太复杂了。幸运的是,在Ubuntu 20.04上,使用xargs
并不复杂。
正如原帖中提到的那样,这个方法可以处理文件中每个参数在单独一行的情况,这也是我所需要的。
cat foo.txt | xargs my_command
需要注意的一点是,似乎无法使用别名命令。
如果命令接受包含多个参数的字符串,则可接受的答案可行。在我的情况下,(Neo)Vim不支持该方法,因为所有参数都被粘在一起了。
xargs
可以正确地执行并提供传递给命令的单独参数。
< foo.txt xargs my_command
或者 xargs < foo.txt my_command
,重定向可以放在任何位置。对于BSD系统,您可以使用 < foo xargs -d \\n cmd
或者 < foo tr \\n \\0 | xargs -0 cmd
。 - CervEd以下是我如何将文件内容作为参数传递给命令:
./foo --bar "$(cat ./bar.txt)"
$(<bar.txt)
基本等效。 $(<foo)
是一个特殊情况:与在$(cat ...)
中使用的常规命令替换不同,它不会分叉出一个子shell进行操作,从而避免了大量的开销。 - Charles Duffy我建议使用:
command $(echo $(tr '\n' ' ' < parameters.cfg))
只需去除行末字符并用空格替换它们,然后将结果字符串作为可能的单独参数使用echo命令输出。
在我的Bash shell中,以下内容可以完美地运行:
cat input_file | xargs -I % sh -c 'command1 %; command2 %; command3 %;'
输入文件是指
arg1
arg2
arg3
正如显而易见的那样,这允许您在每个来自input_file的行中执行多个命令,这是我从这里学到的一个小技巧。
$(somecommand)
的参数,那么这个命令将被执行而不是作为文本传递。同样地,>/etc/passwd
也将被处理为重定向并覆盖 /etc/passwd
(如果以适当的权限运行)。 - Charles Duffyxargs -d $'\n' sh -c 'for arg; do command1 "$arg"; command2 "arg"; command3 "arg"; done' _
。这样更安全,也更高效,因为它会尽可能地将多个参数传递给每个shell,而不是针对输入文件中的每一行启动一个shell。 - Charles Duffycat
。 - tripleee