1

I'm using wget and bash to download a number of sequential files from a URL using {1..####} but am getting the error: Argument list is too long

  1. When I run getconf ARG_MAX it says 262144 - what is this limit in reference to?

  2. What command will increase the argument limit (or can I remove it or set it to infinite?)

5
  • In Terminal getconf ARG_MAX will show the limit. In macOS Catalina it returns: 262144 I do not believe you can set it higher or unlimited, but I'm not 100% sure of that and why I'm posting this as a comment. Commented Oct 19, 2021 at 19:29
  • It's set in syslimits.h as: #define ARG_MAX (256 * 1024) /* max bytes for an exec function */ Commented Oct 19, 2021 at 19:36
  • 2
    I believe you'll have to run multiple wget commands and limit the range of sequential files in each command. Commented Oct 19, 2021 at 19:41
  • Or just run the loop in bash and call wget for each URL.
    – nohillside
    Commented Oct 19, 2021 at 19:43
  • Gotcha. If I break up the files into two sets i.e. {1..100} and {101..200} is there a way to enter one command to run 2 wget functions back-to-back so I don't have to manually enter the second one in after the first finishes? - Also what is the 262144 in reference to, total file size bytes?
    – RobertK
    Commented Oct 19, 2021 at 19:50

2 Answers 2

3
  1. ARG_MAX is the limit (in terms of memory used) on the size of the total argument list + environment variables passed to an executable. See this previous question, and this more detailed explanation.

  2. You can use xargs to split a list of arguments into small-enough-to-process groups, but depending on the form of the arguments (and whether they contain various troublesome characters like whitespace, escapes, quotes etc) this can get complicated. One generally safe way to do it is to use printf '%s\0' to print the argument list with nulls terminating it, then xargs -0 to consume the list:

     printf '%s\0' https://example.com/prefix{1..100}.html | xargs -0 curl -O
    

    Note that any arguments that should be passed to each invocation of the utility (like the -O in this example) must be included in the xargs invocation, not the printf arg list. Also, if there are arguments that need to be passed after the big list, you need a more complex invocation of xargs.

    Also, this may look like it shouldn't work because the huge argument list is still being passed to printf, but that's a shell builtin, not a separate executable, so it's handled inside bash itself and the limit doesn't apply.

[BTW, I thought there must be a previous Q&A covering this, but I couldn't find one. If someone else finds a good one, please mark this question as a duplicate.]

3

When you run

wget 'https://example.com/prefix'{1..9999}'.html'

the expansion of the {1..9999} is done by the shell, resulting in an extremely long list of arguments (run echo foo{1..10} to see what happens).

Instead, you can just run

for i in {1..9999}; do
    wget 'https://example.com/prefix'${i}'.html'
done

or (as a one-liner)

for i in {1..9999}; do wget 'https://example.com/prefix'${i}'.html'; done

to have the shell handle the loop directly and not in the arguments passed to wget. The overall performance of the downloads is limited by the network anyway, so forking and executing 10'000 wget processes (instead of just one) doesn't have a noticeable impact.

PS: Replace 9999 with whatever the highest number is, or use something like {1,7,9,15,22,36} for specific numbers.

7
  • I'm a total newbie to all of this, do I just type all of that as is at once (replacing my number and url) or are they separate commands?
    – RobertK
    Commented Oct 19, 2021 at 20:42
  • 1
    @RobertK , You can type it one line at a time pressing enter after each line, or as a single line like: for i in {1..9999}; do wget https://example.com/prefix${i}.html; done Commented Oct 19, 2021 at 20:51
  • perfect thanks! I assume I can still use the wget commands like -e robots=off in there as well if need be?
    – RobertK
    Commented Oct 19, 2021 at 21:07
  • 1
    @RobertK , RE: "I assume I can still use the wget commands like -e robots=off in there as well if need be?" -- Yes. Commented Oct 19, 2021 at 21:08
  • @RobertK If the URL contains any shell metacharacters (like & separating parameters), you should put double-quotes around it to keep the shell from getting confused by those. (Single-quotes won't work here, because they'd prevent the variable reference ${i} from being expanded (so to speak) into its value. (And if there are any literal dollar-signs in the URL, those'll need to be escaped to prevent them from being treated as variable references). Commented Oct 19, 2021 at 21:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .