在bash(或其他shell)中,是否存在某种字符限制,规定了输入的最大长度?如果是这样的话,那么这个字符限制是多少呢?
换句话说,是否可能在bash中编写一条过长的命令而无法在命令行上执行?如果没有必要的限制,那么是否有建议的限制呢?
在bash(或其他shell)中,是否存在某种字符限制,规定了输入的最大长度?如果是这样的话,那么这个字符限制是多少呢?
换句话说,是否可能在bash中编写一条过长的命令而无法在命令行上执行?如果没有必要的限制,那么是否有建议的限制呢?
命令行长度的限制不是由Shell强制实施的,而是由操作系统决定的。这个限制通常在几百千字节的范围内。POSIX将该限制称为ARG_MAX
,在符合POSIX标准的系统上,可以使用以下命令查询它:
$ getconf ARG_MAX # Get argument limit in bytes
例如,在Cygwin上,这个数字是32000,在我使用的不同BSD和Linux系统上,则从131072到2621440不等。
如果你需要处理一个超过此限制的文件列表,你可以考虑使用xargs
实用程序,它会重复调用一个子集的参数,不超过ARG_MAX
。
回答你具体的问题,是的,可能会尝试运行具有过长参数列表的命令。Shell会报错并显示"argument list too long"的消息。
请注意,程序的输入(如stdin或任何其他文件描述符中读取)并没有受到限制(只受可用程序资源的限制)。因此,如果你的shell脚本读取一个字符串到变量中,你并不受ARG_MAX
的限制。该限制也不适用于shell内置命令。
LONG_VAR
的内容是通过标准输入(stdin)传递的,这完全是在shell中完成的;它不会作为cmd
的参数进行扩展,因此fork()/exec()的ARG_MAX限制并不适用。你可以自己尝试一下:创建一个内容超过ARG_MAX的变量,并运行你的命令。 - Jensblah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null
。请注意没有错误。 - Mike Sxargs
将尝试将多少内容放入一个exec()
中限制为 ARG_MAX - 4096
。因此,使用xargs
的脚本可能会工作,直到有一天某个人在环境中放入了过多的东西。 现在遇到这个问题(可以通过xargs -s ???
绕过它)。 - neuralmerfork()/exec()
的限制,而不是shell在输入行(交互式或非交互式)上可以处理多少内容。因此,这并没有回答问题。(我确实看到一些命令向shell调用其他程序,因此参数会传递到那里,但这是另一回事。) - Robert Siemer好的,居民们。我长期以来一直认为命令行长度限制是不可改变的事实。那么对于这种假设该怎么处理呢?当然是要验证。
我有一台Fedora 22机器(即:带有bash4的Linux)。我创建了一个目录,并在其中放置了500,000个文件,每个文件名18个字符长。命令行长度为9,500,000个字符。创建方式如下:
seq 1 500000 | while read digit; do
touch $(printf "abigfilename%06d\n" $digit);
done
并且我们注意到:
$ getconf ARG_MAX
2097152
然而请注意,我可以做到这一点:
$ echo * > /dev/null
但是这种方法失败了:
$ /bin/echo * > /dev/null
bash: /bin/echo: Argument list too long
我可以运行一个for循环:
$ for f in *; do :; done
这是另一个shell内置命令。
仔细阅读关于ARG_MAX
文档的说明,它说:exec函数参数的最大长度。这意味着:如果不调用exec
,就没有ARG_MAX
限制。这就解释了为什么Shell内置命令没有被ARG_MAX
限制。
实际上,我可以列出我的目录,如果我的参数列表长达109948个文件,或者大约2,089,000个字符(多或少)。但是,一旦我再添加一个18个字符的文件名,我就会收到一个参数列表过长的错误。所以ARG_MAX
正在按照广告宣传的方式工作:exec在参数列表中包含超过ARG_MAX
个字符(包括环境数据)时失败。
for f in *; do echo $f; done
不会分叉(所有内置)。因此,我不知道一个find-xargs组合是否会更快;它还没有经过测试。实际上,我不知道原帖的问题集是什么。也许 find /path/to/directory
对他没有用,因为它会返回文件的路径名。也许他喜欢 for f in *
循环的简单性。无论如何,这次对话是关于行输入限制-而不是效率。因此,让我们保持主题,涉及到命令行长度。” - Mike S有一个大约为1024的缓冲限制。读取将在粘贴或输入过程中中断。要解决这个问题,请使用-e选项。
http://linuxcommand.org/lc3_man_pages/readh.html
-e选项使用Readline在交互式shell中获取行。
将您的read更改为read -e,烦人的行输入中断就消失了。
bash --noediting
,并在新提示符下尝试运行命令echo somereallylongword
,其中somereallylongword的长度超过4090个字符。在Ubuntu 18.04上尝试后,该单词被截断了,所以显然与未启用Readline有关。 - Amirtcsh
每个命令行的字符限制为1024个,如果你有一个非常长的 $PATH
,那么这将变得很困难。我被迫重新构建了一个私有版本的 tcsh,增加了缓冲区大小,以允许用户拥有长的 $PATH
设置。那是20年前的事情。那时候我放弃了使用 tcsh,并转而使用没有这种限制的 zsh。现在我只使用普通的 bash,因为它已经足够好了。