What is the limit of string size passed to bash -c?
2I have the following commandIt doesn't expand the last . Apparently there's a limit on how long the string passed tocan be. Or maybe it is size of the command that can be passed to ? I am curious wha
2
I have the following command
echo '123456789#' | xargs -I% bash -c 'echo %%%%%%%%%%%%%%%%%%%%%%%%%'
It doesn't expand the last %. Apparently there's a limit on how long the string passed to bash -c can be. Or maybe it is size of the command that can be passed to xargs? I am curious what kind of constraint is responsible for this behaviour and can it be configured?
Running
echo 'x' | xargs -I% bash -c 'echo %%%%%%%%%%%%%%%%%%%%%%%%%'
gives xxxxxxxxxxxxxxxxxxxxxxxxx so all 25 occurences of % are expanded, which means it's not the number of occurences of %, but rather length of the resulting string
Note: I run this command on MacOS Ventura 13.6.1
Follow
asked Jul 1, 2024 at 12:25
12144 bronze badges
-
1
See what-defines-the-maximum-size-for-a-command-single-argument but FWIW I see that string repeated 25 times and less tan 250 chars would be very small for aARG_MAXsetting so you may have something else going on. What happens if you useecho 'x' | xargs ...instead? Do you get 25xs or not? From testing with other input strings, is the output truncated at 240 chars or 24 repetitions of the input or something else? Or do you see a literal%at the end of the output? CommentedJul 1, 2024 at 12:36 -
1
In general a good practice is not to embed your % in the shell code in the first place.echo '123456789#' | xargs -I% bash -c 'echo "$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1"' bash %CommentedJul 1, 2024 at 12:42 - @EdMorton I get 25
x– gicig
CommentedJul 1, 2024 at 12:49 -
1
Please edit your question to provide the answers to all of my questions. Don't add information in comments where it can't be formatted and could be missed. Also add the exact output you get from the script you posted. Thanks. CommentedJul 1, 2024 at 12:53 -
1
A portablexargsshall follow this: "At least five arguments in arguments can each contain one or more instances of replstr. Each of these constructed arguments cannot grow larger than an implementation-defined limit greater than or equal to 255 bytes". So maybe it's yourxargsthat is limited; which is another reason to use the code from my first comment where%gets expanded exactly once and the resulting string is short; then the long string to echo is built inbash, not byxargs. CommentedJul 1, 2024 at 13:02
1 Answer
Sorted by:
Highest score (default) Date modified (newest first) Date created (oldest first)
1
Linux has a limit of 128 kB for the length of a single argument string, but that's a lot longer a limit than the string you tried. As far as I understand, most other systems have no specific limit for the length of a single argument, but of course have some limits for their total length (it'll have to be limited by available memory anyway, possibly stack space in particular). If Bash itself has a limit, it's likely long enough for all practical purposes.
Se e.g. this should work:
% bash -c "echo $(printf "1234567890%.0s" {0..30}) | rev"
0987654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321098765432109876543210987654321
The fact that your command leaves some of the %s unexpanded and that it depends on the resulting length, hints at that being an issue of that xargs implementation. (Is it the GNU one? I'm slightly surprised if they have such a low limit.)
In any case, as mentioned in the comments, it's not such a good idea to embed data directly into your shell script as here. It can lead to issues with strange inputs (think quotes), and those can escalate into security problems. Best to avoid doing it.
Instead, pass the data string as an argument to Bash, where it will be available as $1 in the script (the following args being $2, $3 etc).
echo '123456789#' | xargs -I{} bash -c 'echo "$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1$1"' bash {}
(Note that you still can't pass strings with quotes or backslashes (or that start with whitespace) into that without further consideration, since xargs itself does some quote processing on the input unless you use non-standard options such as the -0 / -d of GNU xargs.)
Follow
community wiki
- I forgot to mention (added that in the question) that I was running that command on MacOS Ventura 13.6.1. I guess there is difference between that implemention and one available on Linux
– gicig
CommentedJul 2, 2024 at 9:02 - @gicig, yes, macos has some (possibly old?) version of the FreeBSD toolset, or something like that. They don't support GNU extensions anyway. You just had the question tagged with linux at first, so I guessed at GNU
– ilkkachu
CommentedJul 2, 2024 at 13:18
更多推荐


所有评论(0)