3 Answers
3

The limitation is on the size of the arguments upon execution of a command. So the options are to execute a command with fewer arguments, for instance with xargs to run smaller batches, increase the limit (ulimit -s 100000 on Linux), not execute anything (do it all in the shell), or build the list in the tool that creates the files.

zsh, ksh93, bash:

printf '%s ' {1..1391803} | xargs touch

printf is builtin, so there's no exec, so the limit is not reached. xargs splits the list of args passed to touch to avoid breaking the limit. That's still not very efficient as the shell has to first create the whole list (slow especially with bash), store it in memory, and then print it.

seq 1391803 | xargs touch

(assuming you have a seq command) would be more efficient.

for ((i=1; i<=1391803; i++)); do : >> "$i"; done

Everything is done in the shell, no big list stored in memory. Should be relatively efficient except maybe with bash.

In your example, Bash complains because when expanding test_{1..1391803}.txt it ends up with a too long argument command line. The maximum length of the command line which can be passed to a command is fixed by the kernel, because the exec system call which is responsible of starting new processes (in fact, replacing the program of an existing process by another) must put those arguments in the stack of the process and the size of the stack is limited.

I think the most efficient way to do this would be not to start a new touch process each time you want a file.

You could in ruby for example:

ruby -e '1.upto(1391803) { |n| File.open("test_#{n}.txt", "w") {} }'

This way, you start only one process which will create all the files without the need to launch the touch program.

This command launches the ruby interpreter. Then ruby builds a loop over the range 1..1391803 and for each number, calls the function File.open which executes the open system call with a file name built with the number. As the block after File.open is empty, the file is immediately closed.