Skip to main content

A partial and opinionated implementation of xargs in python with some added features

Project description


This started as a simple solution to the encoding problem with xargs. It is a partial and opinionated implementation of xargs with the goal of being easier to use for most use cases.

It also contains some additional features which may or may not be useful, such as taking python code as arguments to be executed, or filtering input with regular expressions. No new features are planned.

You can install pyxargs from PyPI.

Command Line Interface

usage: pyxargs [options] command [initial-arguments ...]
       pyxargs -h | --help | --examples | --version

Build and execute command lines or python code from standard input or file
paths, a partial and opinionated implementation of xargs in python with some
added features. The file input mode (default if stdin is not connected) builds
commands using filenames only and executes them in their respective
directories, this is useful when dealing with file paths containing multiple
character encodings.

  -h, --help            show this help message and exit
  --examples            show example usage and exit
  --version             show program's version number and exit
  -m input-mode         options are:
                        file    = build commands from filenames and execute in
                                  each subdirectory respectively
                        path    = build commands from file paths relative to
                                  the current directory and execute in the
                                  current directory
                        abspath = build commands from absolute file paths and 
                                  execute in the current directory
                        stdin   = build commands from standard input and
                                  execute in the current directory
                        default: stdin if connected, otherwise file
  --folders             use folders instead files (for input modes: file,
                        path, abspath)
  -t, --top             do not recurse into subdirectories (for input modes:
                        file, path, abspath)
  --sym, --symlinks     follow symlinks when scanning directories (for input
                        modes: file, path, abspath)
  -a file, --arg-file file
                        read input items from file instead of standard input
                        (for input mode: stdin)
  -0, --null            input items are separated by a null character instead
                        of whitespace (for input mode: stdin)
  -d delim, --delimiter delim
                        input items are separated by the specified delimiter
                        instead of whitespace (for input mode: stdin)
  -s regex, --split regex
                        split each input item with re.split(regex, input)
                        before building command (after separating by
                        delimiter), use {0}, {1}, ... to specify placement
                        (implies --format)
  -f, --format          format command with input using str.format() instead
                        of appending or replacing via -I replace-str
  -I replace-str        replace occurrences of replace-str in command with
                        input, default: {}
  --resub pattern substitution replace-str
                        replace occurrences of replace-str in command with
                        re.sub(patten, substitution, input)
  -r regex              only build commands from inputs matching regex for
                        input mode stdin, and matching relative paths for all
                        other input modes, uses
  -o                    omit inputs matching regex instead
  -b                    only match regex against basename of input (for input
                        modes: file, path, abspath)
  --max-chars n         omits any command line exceeding n characters, no
                        limit by default
  --sh, --shell         executes commands through the shell (subprocess
                        shell=True) (no effect on Windows)
  --py, --pyex          executes commands as python code using exec()
  --pyev                evaluates commands as python expressions using eval()
  --import library      executes 'import <library>' for each library
  --im library, --importstar library
                        executes 'from <library> import *' for each library
  --pre "code"          runs exec(code) before execution
  --post "code"         runs exec(code) after execution
  -P P, --procs P       split into P chunks and execute each chunk in parallel
                        as a separate process and window with byobu or tmux
  -c c, --chunk c       runs chunk c of P (0 <= c < P) (without multiplexer)
  --no-mux              do not use a multiplexer for multiple processes
  -i, --interactive     prompt the user before executing each command, only
                        proceeds if response starts with 'y' or 'Y'
  -n, --dry-run         prints commands without executing them
  -v, --verbose         prints commands before executing them


# by default, pyxargs will use filenames and run commands in each directory
  > pyxargs echo

# instead of appending inputs, you can specify a location with {}
  > pyxargs echo spam {} spam

# and like xargs, you can also specify the replace-str with -I
  > pyxargs -I eggs echo spam eggs spam literal {}

# if stdin is connected, it will be used instead of filenames by default
  > echo bacon eggs | pyxargs echo spam

# python code can be used in place of a command
  > pyxargs --py "print(f'input file: {} executed in: {os.getcwd()}')"

# python code can also run before or after all the commands
  > pyxargs --pre "n=0" --post "print(n,'files')" --py "n+=1"

# regular expressions can be used to filter and modify inputs
  > pyxargs -r \.py --resub \.py .txt {new} echo {} -\> {new}

# you can test your command first with --dry-run (-n) or --interactive (-i)
  > pyxargs -i echo filename: {}

# pyxargs can also run interactively in parallel by using byobu or tmux
  > pyxargs -P 4 -i echo filename: {}

# you can use pyxargs to create a JSON mapping of /etc/hosts
  > cat /etc/hosts | pyxargs -d \n --im json --pre "d={}" \
    --post "print(dumps(d))" --py "d['{}'.split()[0]] = '{}'.split()[1]"

# you can also do this with format strings and --split (-s) (uses regex)
  > cat /etc/hosts | pyxargs -d \n -s "\s+" --im json --pre "d={}" \
    --post "print(dumps(d))" --py "d['{0}'] = '{1}'"

# this and the following examples will compare usage with find & xargs
  > find ./ -name "*" -type f -print0 | xargs -0 -I {} echo {}
  > find ./ -name "*" -type f -print0 | pyxargs -0 -I {} echo {}

# pyxargs does not require '-I' to specify a replace-str (default: {})
  > find ./ -name "*" -type f -print0 | pyxargs -0 echo {}

# and in the absence of a replace-str, exactly one input is appended
  > find ./ -name "*" -type f -print0 | pyxargs -0 echo
  > find ./ -name "*" -type f -print0 | xargs -0 --max-args=1 echo
  > find ./ -name "*" -type f -print0 | xargs -0 --max-lines=1 echo

# pyxargs can use file paths as input without piping from another program
  > pyxargs -m path echo ./{}

# and now for something completely different, python code for the command
  > pyxargs -m path --py "print('./{}')"

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyxargs-2.4.2.tar.gz (21.2 kB view hashes)

Uploaded source

Built Distribution

pyxargs-2.4.2-py3-none-any.whl (22.6 kB view hashes)

Uploaded py3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page