# Xargs `L_xargs` is a high-performance, pure-Bash implementation of the `xargs` utility, designed for seamless integration with local shell environments. ## User Guide Unlike the standard GNU `xargs` which is a compiled binary, `L_xargs` runs within the current shell context. This allows it to directly execute Bash functions, use aliases, and access shell variables without needing to export them. It is a powerful tool for building complex data-processing pipelines directly in Bash. ### The Processing Pipeline: Records and Atoms `L_xargs` operates on two levels of input units: 1. **Records:** These are the primary chunks of input, separated by a delimiter. By default, the delimiter is a newline character (`\n`), so each line of input is one record. You can change this with the `-d` (delimiter) or `-0` (null character) options. 2. **Atoms:** These are the final arguments that are passed to the command being executed. By default, `L_xargs` splits each Record into Atoms using shell-like quoting rules (split mode). Use `-Z` to treat each Record as a single, solid Atom. The command is executed when either the number of accumulated Atoms reaches the limit set by `-n`, or the number of Records reaches the limit set by `-L`. ### Key Features and Differences from GNU xargs - **Shell Integration:** The most significant advantage. `L_xargs` can call shell functions and aliases directly, which is impossible with standard `xargs` without using `export -f`. - **Advanced Input Sources:** `L_xargs` can read items from a Bash array (`-A `) or a custom callback function (`-C `), in addition to `stdin`. - **Performance:** While highly optimized for shell environments, `L_xargs` is a pure Bash implementation and will generally be slower than the native C-based GNU `xargs`. For most scripting tasks, its flexibility and integration are more valuable. - **Granular Return Codes:** Provides specific return codes (123, 124, 125, etc.) to indicate different failure modes, allowing for more robust error handling. ### Basic Usage ```bash # Reads newline-separated items from stdin and passes them as arguments to echo printf "item1\nitem2\nitem3" | L_xargs # Output: item1 item2 item3 ``` **Default command**: `echo`. Use an explicit command like `L_quote_printf` if you want shell-quoted output. ### Options and Examples #### Executing a Shell Function This is a primary use case for `L_xargs`. The function does not need to be exported. Because `L_xargs` operates within the same shell, the function can also access any variables or other functions from your script. By default, `L_xargs` executes commands in a subshell (forked process). To run the function in the *current shell execution environment* (so modifications to variables persist), use the `-F` (foreground) option. ```bash #!/usr/bin/env bash . L_lib.sh -s my_prefix="Item" counter=0 # This function can access and modify variables from the script process_item() { echo "Processing $my_prefix: $1" (( counter++ )) } # Use -F to run in current shell so counter persists L_xargs -F -n 1 process_item <<<$'A\nB\nC' echo "Total items processed: $counter" # Output: # Processing Item: A # Processing Item: B # Processing Item: C # Total items processed: 3 ``` #### Input from an Array (-A) Use the `-A` option to read input directly from a Bash array. ```bash my_items=("First item" "Second item" "Third item") # -Z ensures each element is a single argument L_xargs -Z -A my_items -n 1 echo # Output: # First item # Second item # Third item ``` #### Input from a Callback Function (-C) The `-C` option allows you to provide a string that will be `eval`ed to generate input Records. The evaluated string must populate the `L_RET` variable (as an array) and return 0 for success. A non-zero return code signals the end of input. ```bash i=0 generate_items() { if (( i < 3 )); then L_RET="item_$((++i))" return 0 fi return 1 } L_xargs -n 1 -C 'generate_items' echo # Output: # item_1 # item_2 # item_3 ``` #### Delimiter and Record Handling (-d, -0) By default, `L_xargs` uses a newline to separate records. `-d` changes the delimiter. `-0` is a shorthand for `-d ''`, using the null character, which is useful for working with `find -print0`. By default, `L_xargs` splits each record into atoms using shell-like quoting rules (split mode). Use `-Z` to treat each record as a single, solid atom. ```bash # Default behavior (Split mode) printf "A B\nC" | L_xargs -n 1 echo # Output: # A # B # C # Solid mode printf "A B\nC" | L_xargs -Z -n 1 echo # Output: # A B # C ``` #### Parallel Execution (-P) Use `-P` to run commands in parallel. `-P nproc` is a convenient shortcut to use all available CPU cores. ```bash # Run up to 4 sleep commands in parallel printf "1\n2\n3\n4" | L_xargs -P 4 -n 1 sleep ``` #### Ordered Parallel Output (-O) When running in parallel with `-P`, output from different commands can be interleaved. The `-O` option ensures that the output from each command is buffered and printed atomically once the command completes. This prevents interleaving but may result in output order not matching the input order. ```bash # Without -O, output can be mixed. printf "A\nB" | L_xargs -P 2 -n 1 -- bash -c 'echo "start $1"; sleep 0.1; echo "end $1"' -- # Output: # start A # start B # end B # end A # With -O, each command's output is grouped. printf "A\nB" | L_xargs -O -P 2 -n 1 -- bash -c 'echo "start $1"; sleep 0.1; echo "end $1"' -- # Output: # start A # end A # start B # end B ``` #### Controlling Command Execution (-n, -L) `-n` (max-atoms) and `-L` (max-records) control how many items are processed before the command is executed. The command is triggered as soon as *either* limit is reached. * **`-n 2`**: Executes the command for every 2 atoms collected. * **`-L 2`**: Executes the command for every 2 records read. * **`-n 2 -L 3`**: If 2 atoms are collected *before* 3 records are read, the command runs. If 3 records are read *before* 2 atoms are collected, the command runs. Example: ```bash # -z splits "A B" into two atoms. The -n 2 limit is hit after the first line. # The command runs, and the limits are reset. Then "C" is processed. printf "A B\nC" | L_xargs -z -n 2 -L 3 echo # Output: # A B # C ``` #### Prefixing Output (-^) The `-^` option prepends the arguments used for the command, followed by a colon, to each line of the command's output. ```bash printf "A\nB" | L_xargs -n 1 -^ -- L_eval 'echo "Line 1 of $1"; echo "Line 2 of $1"' # Output: # A: Line 1 of A # A: Line 2 of A # B: Line 1 of B # B: Line 2 of B ``` ## API Reference ::: bin/L_lib.sh xargs