Overcome command line length limitations

Author: name contact BSD flavour

Reviewer: name contact BSD flavour

Reviewer: name contact BSD flavour


Concept

The command line length is limited, and often a command should be applied to more arguments than fit on a command line. Understand how to run the command multiple times with different arguments for each call using xargs(1)(((xargs))) or a shell "while(((while)))" read loop.

Introduction

The shell has a limit for the command line length and the system has a limit on how many bytes can be used for the arguments (and environment variables) when starting a new process. (Some shells also have a limit on the command line length saved in its history.)

NOTES:

TODO: Just briefly mention the following, but focus on generic skills of using xargs and sh while loop instead of adjusting the more advanced tunables.

ksh 1024 on command line

tcsh 8190 on command line

tcsh history is 4096

On DragonFly: TODO: sh has "abort" or "segmentation fault" and exits noticed with around 1920 characters -- report this bug or commit fix

NCARGS on FreeBSD and DragonFly is 65536. On OpenBSD and NetBSD it is 262144

TODO: mention "getconf ARG_MAX"??

TODO: do all BSD's have kern.argmax?

Common error message is "Argument list too long."

TODO: some xargs have -J option for replacements, but I probably won't cover that here and will use "while" instead

TODO: mention find -print0 and xargs -0

TODO: example using Bourne style shell:

"" find . -type f | while read line ; do "" # do something with ${line} "" done

TODO: do real example above

Examples

The following is an example of having too many arguments:

"" $ ls -l /usr/ports/*/*/Makefile* "" /bin/ls: Argument list too long.

A work-around for this is to use shell built-in "echo" and pipe the output to "xargs", for example:

""$ echo /usr/ports/*/*/Makefile* | xargs ls -l

(Note that that output is not shown here, because it was over 15,000 lines.)

Practice Exercises

run a command multiple times with different arguments for each call: ls | xargs md5 (spits out an md5 hash for each file in a dir)

More information

xargs(1), find(1)