Git Product home page Git Product logo

parallel's Introduction

MIT/Rust Parallel: A Command-line CPU Load Balancer Written in Rust

Crates.io Tokei SLoC Count AUR OpenHub Statistics

This is an attempt at recreating the functionality of GNU Parallel, a work-stealer for the command-line, in Rust under a MIT license. The end goal will be to support much of the functionality of GNU Parallel and then to extend the functionality further for the next generation of command-line utilities written in Rust. While functionality is important, with the application being developed in Rust, the goal is to also be as fast and efficient as possible.

Note

See the to-do list for features and improvements that have yet to be done. If you want to contribute, pull requests are welcome. If you have an idea for improvement which isn't listed in the to-do list, feel free to email me and I will consider implementing that idea.

Benchmark Comparison to GNU Parallel

Note: Parallel in these benchmarks is compiled with MUSL instead of glibc. This is highly recommended as it reduces memory consumption by half and doubles performance.

Printing 1 to 10,000 in parallel

GNU Parallel

~/D/parallel (master) $ seq 1 10000 | time -v /usr/bin/parallel echo > /dev/null
    User time (seconds): 194.73
    System time (seconds): 66.49
    Percent of CPU this job got: 230%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 1:53.08
    Maximum resident set size (kbytes): 16140

Rust Parallel (Built with MUSL target)

~/D/parallel (master) $ seq 1 10000 | time -v target/release/x86_64-unknown-linux-musl/parallel echo > /dev/null
    User time (seconds): 0.40
	System time (seconds): 2.53
	Percent of CPU this job got: 97%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.01
    Maximum resident set size (kbytes): 1768

Cat the contents of every binary in /usr/bin

GNU Parallel

~/D/parallel (master) $ time -v /usr/bin/parallel cat ::: /usr/bin/* > /dev/null
    User time (seconds): 71.71
    System time (seconds): 27.67
    Percent of CPU this job got: 222%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:44.62
    Maximum resident set size (kbytes): 17576

Rust Parallel (Built with MUSL target)

~/D/parallel (master) $ time -v target/release/x86_64-unknown-linux-musl/release/parallel cat ::: /usr/bin/* > /dev/null
    User time (seconds): 1.07
	System time (seconds): 4.40
	Percent of CPU this job got: 191%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 0:02.86
    Maximum resident set size (kbytes): 1844

Logging echo ::: $(seq 1 1000)

GNU Parallel

~/D/parallel (master) $ time -v /usr/bin/parallel --joblog log echo ::: $(seq 1 1000) > /dev/null
    User time (seconds): 21.27
    System time (seconds): 7.44
    Percent of CPU this job got: 238%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:12.05
    Maximum resident set size (kbytes): 16624

Rust Parallel (Built with MUSL target)

~/D/parallel (master) $ time -v target/x86_64-unknown-linux-musl/release/parallel --joblog log echo ::: $(seq 1 1000) > /dev/null
    User time (seconds): 0.02
    System time (seconds): 0.28
    Percent of CPU this job got: 85%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.36
    Maximum resident set size (kbytes): 1768

Syntax Examples

The following syntax is supported:

parallel 'echo {}' ::: *                          // {} will be replaced with each input found.
parallel echo ::: *                               // If no placeholders are used, it is automatically assumed.
parallel echo :::: list1 list2 list3              // Read newline-delimited arguments stored in files.
parallel echo ::: arg1 ::::+ list :::+ arg2       // Interchangeably read arguments from the command line and files.
parallel echo ::: 1 2 3 ::: A B C ::: D E F       // Permutate the inputs.
parallel echo '{} {1} {2} {3.}' ::: 1 2 file.mkv  // {N} tokens are replaced by the Nth input argument
parallel ::: "echo 1" "echo 2" "echo 3"           // If no command is supplied, the input arguments become commands.
parallel 'cd {}; echo Directory: {}; echo - {}'   // Commands may be chained in the platform\'s shell.
seq 1 10 | parallel 'echo {}'                     // If no input arguments are supplied, stdin will be read.
seq 1 10 | parallel --pipe cat                    // Piping arguments to the standard input of the given command.
#!/usr/bin/parallel --shebang echo                // Ability to use within a shebang line.

Manual

Parallel parallelizes otherwise non-parallel command-line tasks. When there are a number of commands that need to be executed, which may be executed in parallel, the Parallel application will evenly distribute tasks to all available CPU cores. There are three basic methods for how commands are supplied:

  1. A COMMAND may be defined, followed by an which denotes that all following arguments will be used as INPUTS for the command.

  2. If no COMMAND is provided, then the INPUTS will be interpreted as COMMANDS.

  3. If no INPUTS are provided, then standard input will be read for INPUTS.

Parallel groups the standard output and error of each child process so that outputs are printed in the order that they are given, as if the tasks were executed serially in a traditional for loop. In addition, commands are executed in the platform's preferred shell by default, which is sh -c on Unix systems, and cmd /C on Windows. This comes at a performance cost, so it can be disabled with the --no-shell option.

INPUT MODES

Input modes are used to determine whether the following inputs are files that contain inputs or inputs themselves. Files with inputs have each input stored on a separate line, and each line is considered an entire input.When there are multiple collected lists of inputs, each individual input list will be permutated together into a single list.

  • :::

Denotes that the input arguments that follow are input arguments. Additionally, those arguments will be collected into a new list.

  • :::+

Denotes that the input arguments that follow are input arguments. Additionally, those arguments will be added to the current list.

  • ::::

Denotes that the input arguments that follow are files with inputs. Additionally, those arguments will be collected into a new list.

  • ::::+

Denotes that the input arguments that follow are files with inputs. Additionally, those arguments will be added to the current list.

INPUT TOKENS

COMMANDs are typically formed the same way that you would normally in the shell, only that you will replace your input arguments with placeholder tokens like {}, {.}, {/}, {//} and {/.}. If no tokens are provided, it is inferred that the final argument in the command will be {}. These tokens will perform text manipulation on the inputs to mangle them in the way you like. Ideas for more tokens are welcome.

  • {}: Each occurrence will be replaced with the name of the input.
  • {.}: Each occurrence will be replaced with the input, with the extension removed.
  • {^abc...}: Each occurrence will be replaced with a custom suffix removed
  • {/}: Each occurrence will be replaced with the base name of the input.
  • {/.}: Each occurrence will be replaced with the base name of the input, with the extension removed.
  • {/^abc...}: Each occurrence will be replaced with the base name of the input, with a custom suffix removed.
  • {//}: Each occurrence will be replaced with the directory name of the input.
  • {%}: Each occurrence will be replaced with the slot number.
  • {#}: Each occurrence will be replaced with the job number.
  • {##}: Each occurrence will be replaced with the total number of jobs.
  • {N}: Where N is a number, display the associated job number.
  • {N.}: Will remove the extension from the Nth job.
  • {N^abc...}: Defines a custom suffix to remove from the Nth job, if found.
  • {N/}: Displays the base name (file name) of the Nth job.
  • {N//}: Displays the directory name of the Nth job.
  • {N/.}: Displays the base name of the Nth job with the extension removed.
  • {N/^abc...}: Displays the basename of the Nth job, with a custom suffix removed.

OPTIONS

Options may also be supplied to the program to change how the program operates:

  • --delay: Delays starting the next job for N amount of seconds, where the seconds can be fractional.
  • --dry-run: Prints the jobs that will be run to standard output, without running them.
  • --eta: Prints the estimated time to complete based on average runtime of running processes.
  • -h, --help: Prints the manual for the application (recommended to pipe it to less).
  • -j, --jobs: Defines the number of jobs/threads to run in parallel.
  • --joblog: Logs job statistics to a designated file as they are completed.
  • --joblog-8601: Writes the start time in the ISO 8601 format: YYYY-MM-DD hh:mm:ss
  • --memfree: Defines the minimum amount of memory available before starting the next job.
  • -n, --max-args: Groups up to a certain number of arguments together in the same command line.
  • --num-cpu-cores: Prints the number of CPU cores in the system and exits.
  • -p, --pipe: Instead of supplying arguments as arguments to child processes, instead supply the arguments directly to the standard input of each child process.
  • -q, --quote: Escapes the command argument supplied so that spaces, quotes, and slashes are retained.
  • -s, --silent, --quiet: Disables printing the standard output of running processes.
  • --shebang: Grants ability to utilize the parallel command as an interpreter via calling it within a shebang line.
  • --shellquote: Prints commands that will be executed, with the commands quoted.
  • --tmpdir: Defines the directory to use for temporary files
  • --timeout: If a command runs for longer than a specified number of seconds, it will be killed with a SIGKILL.
  • -v, --verbose: Prints information about running processes.
  • --version: Prints the current version of the application and it's dependencies.

Useful Examples

Transcoding FLAC music to Opus

ffmpeg is a highly useful application for converting music and videos. However, audio transcoding is limited to a a single core. If you have a large FLAC archive and you wanted to compress it into the efficient Opus codec, it would take forever with the fastest processor to complete, unless you were to take advantage of all cores in your CPU.

parallel 'ffmpeg -v 0 -i "{}" -c:a libopus -b:a 128k "{.}.opus"' ::: $(find -type f -name '*.flac')

Transcoding Videos to VP9

VP9 has one glaring flaw in regards to encoding: it can only use about three cores at any given point in time. If you have an eight core processor and a dozen or more episodes of a TV series to transcode, you can use the parallel program to run three jobs at the same time, provided you also have enough memory for that.

vp9_params="-c:v libvpx-vp9 -tile-columns 6 -frame-parallel 1 -rc_lookahead 25 -threads 4 -speed 1 -b:v 0 -crf 18"
opus_params="-c:a libopus -b:a 128k"
parallel -j 3 'ffmpeg -v 0 -i "{}" $vp9_params $opus_params -f webm "{.}.webm"' ::: $(find -type f -name '*.mkv')

Installation Instructions

There are a number of methods that you can use to install the application. I provide binary packages for AMD64 systems that are available for download:

Gentoo

I have a personal Gentoo layman overlay that provides this application for installation.

Arch Linux

A PKGBUILD is available for Arch Linux users from the AUR.

Everyone Else

rustup target add x86_64-unknown-linux-musl
wget https://github.com/mmstick/parallel/archive/master.zip
unzip master.zip
cd parallel-master
cargo build --release --target x86_64-unknown-linux-musl
sudo install target/x86_64-unknown-linux-musl/release/parallel /usr/local/bin/parallel

parallel's People

Contributors

ajyoon avatar ignatenkobrain avatar lnicola avatar michael-grunder avatar mmstick avatar sanga avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

parallel's Issues

Confusing behaviour from --help

It looks like --help is interpreted as a command, to be executed.

> parallel --help
(seems to hang)
a
b
(ctrl+d)

sh: --: invalid option
Usage:  sh [GNU long option] [option] ...
    sh [GNU long option] [option] script-file ...
GNU long options:
    --debug
    --debugger
    --dump-po-strings
    --dump-strings
    --help
    --init-file
    --login
    --noediting
    --noprofile
    --norc
    --posix
    --protected
    --rcfile
    --restricted
    --verbose
    --version
    --wordexp
Shell options:
    -irsD or -c command or -O shopt_option      (invocation only)
    -abefhkmnptuvxBCHP or -o option
sh: --: invalid option
Usage:  sh [GNU long option] [option] ...
    sh [GNU long option] [option] script-file ...
GNU long options:
    --debug
    --debugger
    --dump-po-strings
    --dump-strings
    --help
    --init-file
    --login
    --noediting
    --noprofile
    --norc
    --posix
    --protected
    --rcfile
    --restricted
    --verbose
    --version
    --wordexp
Shell options:
    -irsD or -c command or -O shopt_option      (invocation only)
    -abefhkmnptuvxBCHP or -o option

subprocess stdout/stderr jumbled

Unlike GNU parallel, this tool isn't capturing stdout/stderr from the child process, which results in a mishmash of jumbled output. Needs an equivalent of the --group and --ungroup options from GNU parallel (default behaviour with GNU parallel is to use --group).

RFC: Package/Binary naimng

Since I'm packaging this for Fedora I would like to get opinion on naming.. Since parallel name is taken by GNU parallel, I am thinking how to name package and whether to rename binary.

  • rust-parallel
  • parallel-rust
  • parallel-rs

Thoughts?

--dry-run isn't what gets executed

~>> echo ./zoomed\ in.png
./zoomed in.png
~> echo ./zoomed\ in.png | parallel 'file -ib "{}"'
parallel: reading inputs from standard input
cannot open `"./zoomed in.png"' (No such file or directory)
~> echo ./zoomed\ in.png | parallel --dry-run 'file -ib "{}"'
parallel: reading inputs from standard input
file -ib "./zoomed in.png"
~> file -ib "./zoomed in.png"
image/png; charset=binary

Any idea why parallel isn't working here? The output of --dry-run is correct.

cannot be built with rust 1.11

  Compiling parallel v0.0.1 (https://github.com/mmstick/parallel#ad8242d3)
<std macros>:2:21: 2:52 error: expected token: `,`
<std macros>:2 $ dst . write_fmt ( format_args ! ( $ ( $ arg ) * ) ) )
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/freundt/.cargo/git/checkouts/parallel-0c6613aa1b32f1b5/master/src/main.rs:41:25: 41:94 note: in         this expansion of write! (defined in <std macros>)
error: aborting due to previous error
error: failed to compile `parallel v0.0.1 (https://github.com/mmstick/parallel#ad8242d3)`, intermediate     artifacts can be found at `/tmp/cargo-install.3ye1sxZy0nYq`

Caused by:
  Could not compile `parallel`.

3x slower than GNU parallel on "cat" command and parameters on stdin

I've tested Rust parallel on 10,000 files and it's now significantly slower on a simple 'cat' workload than gnu parallel. The command line is:

find '/folder/with/lots/of/text/files/' -type f | head -n 10000 | parallel -j 6 cat '{}' > /dev/null

Runtime and peak memory usage for each:
rust: 1:40, 36,8MiB
rust, --no-shell: 1:36, 58,9MiB
gnu: 0:31, 14,6MiB

Additionally, the memory usage for Rust parallel grows over time while GNU parallel uses a fixed amount of memory.

For the record, the regular use case for this is piping all that stuff to grep instead of /dev/null to get aggregate statistics for the entire dataset.

"command error: Resource temporarily unavailable (os error 11)" when processing a lot of files

When invoking Parallel 70,000 files with filenames piped on stdin, its memory usage grows continously up to 0,5Gb of RAM, and when it stops growing Parallel starts spamming the following line:

parallel: command error: Resource temporarily unavailable (os error 11)

Happens both with and without --no-shell argument. Command line to reproduce the issue:

find '/some/folder/with/tens/of/thousands/of/files' -type f | 'target/release/parallel' -j 6 cat '{}' > /dev/null

Parallel built from git with cargo build --release on Linux x86_64, rustc 1.11.0 (9b21dcd6a 2016-08-15)

parallel complains if no arguments are passed

Parallel complains if no arguments are passed. However, it should be fine to write something like:

echo 'echo Hello' | parallel

If I just pick an argument to add (like -n or -q or -v) then the code runs fine as I expect.

Parallel doesn't play well with filenames containing a quote

Hello, it's me again with my filenames problems

I'm gonna take an example to explain the situation.

Say we have two folders with files to move.

mkdir folder1 folder2
touch "folder1/Let'sgo.txt" "folder1/Let'sgo-q1.txt" "folder1/Let'sgo-q2.txt" "folder1/Let'sgo-q3.txt"
export file="Let'sgo"

I can move a file containing a quote with mv without any problem:

mv "folder1/${file}.txt" "folder2/."

However if I try to use parallel to do the same thing, I get an error:

seq 1 3 | parallel mv "folder1/${file}-q{}.txt" "folder2/."

parallel: reading inputs from standard input
mv: missing destination file operand after 'folder1/Letsgo-q1.txt folder2/.'
Try 'mv --help' for more information.
mv: missing destination file operand after 'folder1/Letsgo-q2.txt folder2/.'
Try 'mv --help' for more information.
mv: missing destination file operand after 'folder1/Letsgo-q3.txt folder2/.'
Try 'mv --help' for more information.

It seems parallel remove the quote from my filename or misinterpret it, despite it being inside an enclosed variable.

If I escape the quote, it works:

seq 1 3 | parallel mv "folder1/Let\'sgo-q{}.txt" "folder2/."

but it's not really a workable solution because I feed filenames as a variable inside a bigger script. I think there shouldn't be any difference of behaviour between a non-parallelized function and a parallelized one.

Separator / NUL support

GNU parallel has a -0 option to use with the same option of find. Is this just missing or it's by design?

example comparing parallel with gnu-parallel is nowhere close to the times posted

seq 1 10000 | time -v rust-parallel echo > /dev/null

    Command being timed: "rust-parallel echo"
    User time (seconds): 2.03
    System time (seconds): 84.76
    Percent of CPU this job got: 407%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:21.29
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 27516
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 1220681
    Voluntary context switches: 80355
    Involuntary context switches: 21519
    Swaps: 0
    File system inputs: 0
    File system outputs: 176
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

problems when building

Hi, I wanted to give a try to parallel.

I installed rust and cargo on my kubuntu box with apt-get, cloned the repo and ran:
cargo build

I got the errors below. Could you please provide some guidance?

unused manifest key: package.metadata.deb.assets
unused manifest key: package.metadata.deb.assets
unused manifest key: package.metadata.deb.assets
unused manifest key: package.metadata.deb.assets
unused manifest key: package.metadata.deb.assets
unused manifest key: package.metadata.deb.assets
unused manifest key: package.metadata.deb.copyright
unused manifest key: package.metadata.deb.depends
unused manifest key: package.metadata.deb.extended_description
unused manifest key: package.metadata.deb.license_file
unused manifest key: package.metadata.deb.license_file
unused manifest key: package.metadata.deb.maintainer
unused manifest key: package.metadata.deb.priority
unused manifest key: package.metadata.deb.section
Compiling permutate v0.1.3 (file:///home/nadim/nadim/devel/repositories/rust-parallel)
Compiling libc v0.2.15 (file:///home/nadim/nadim/devel/repositories/rust-parallel)
deps/permutate/src/lib.rs:145:55: 145:64 error: use of unstable library feature 'iter_arith': bounds recently changed (see issue #27739)
deps/permutate/src/lib.rs:145 let max_iters = nvalues.iter().map(|x| x + 1).product();
^~~~~~~~~
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
Could not compile permutate.

To learn more, run the command again with --verbose.

Question: Is nightly rust still needed?

Quite a few versions of rust have been promoted to stable since this project was published. Is nightly still needed, or have all of the relevant features been incorporated in a recent stable release?

--quote for arguments?

I originally understood --quote to escape the {...} substitutions, not the command. Maybe it should escape both?

~> echo "hello 'world'" | parallel --quote --dry-run file -ib
parallel: reading inputs from standard input
file -ib hello 'world'

To obtain the following output:

file -b hello\ \'world\'

In fact, I'd argue that the default behavior is that input converted to arguments should be escaped before substitution.

Input validation: panic with `parallel --shell`

mqudsi@ZBook /m/c/U/M/Downloads> parallel --shell
thread 'main' panicked at 'byte index 9 is out of bounds of `--shell`', /checkout/src/libcore/str/mod.rs:2171:8
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
             at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::_print
             at /checkout/src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at /checkout/src/libstd/sys_common/backtrace.rs:60
             at /checkout/src/libstd/panicking.rs:380
   3: std::panicking::default_hook
             at /checkout/src/libstd/panicking.rs:396
   4: std::panicking::rust_panic_with_hook
             at /checkout/src/libstd/panicking.rs:611
   5: std::panicking::begin_panic_new
             at /checkout/src/libstd/panicking.rs:553
   6: std::panicking::begin_panic_fmt
             at /checkout/src/libstd/panicking.rs:521
   7: rust_begin_unwind
             at /checkout/src/libstd/panicking.rs:497
   8: core::panicking::panic_fmt
             at /checkout/src/libcore/panicking.rs:92
   9: core::str::slice_error_fail
             at /checkout/src/libcore/str/mod.rs:2171
  10: parallel::arguments::Args::parse
  11: parallel::main
  12: __rust_maybe_catch_panic
             at /checkout/src/libpanic_unwind/lib.rs:98
  13: std::rt::lang_start
             at /checkout/src/libstd/panicking.rs:458
             at /checkout/src/libstd/panic.rs:361
             at /checkout/src/libstd/rt.rs:59
  14: __libc_start_main
  15: _start

Referencing argument from input list n

In GNU parallel, the token {2} means "argument from second input list", whereas here it means "argument from second job". As far as I can see, there's no way to get the first behavior with rust parallel? This makes multiple argument lists less useful.

Example from the GNU parallel man page:

GNU parallel:

% parallel echo {1} {2} {3} ::: 6 7 ::: 4 5 ::: 1 2 3
6 4 1
6 4 2
6 4 3
6 5 1
6 5 2
6 5 3
7 4 1
7 4 2
7 4 3
7 5 1
7 5 2
7 5 3

Rust parallel:

% parallel echo {1} {2} {3} ::: 6 7 ::: 4 5 ::: 1 2 3
6 4 1 6 4 2 6 4 3 6 4 1
6 4 1 6 4 2 6 4 3 6 4 2
6 4 1 6 4 2 6 4 3 6 4 3
6 4 1 6 4 2 6 4 3 6 5 1
6 4 1 6 4 2 6 4 3 6 5 2
6 4 1 6 4 2 6 4 3 6 5 3
6 4 1 6 4 2 6 4 3 7 4 1
6 4 1 6 4 2 6 4 3 7 4 2
6 4 1 6 4 2 6 4 3 7 4 3
6 4 1 6 4 2 6 4 3 7 5 1
6 4 1 6 4 2 6 4 3 7 5 2
6 4 1 6 4 2 6 4 3 7 5 3

Error compiling

How does one enable support for the '?' operator used since 783a...

rustc --version: rustc 1.12.1 (d4f39402a 2016-10-19)

error: the ? operator is not stable (see issue #31436)
--> src/tokenizer/mod.rs:158:44
|
158 | let argument = Number::new(number, token).into_argument(path)?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 52 previous errors

error: Could not compile parallel.

panic on empty lines

When running an input from stdin, if any line is blank I get the following error. Obviously a blank line is silly, but easy to do if you are constructing the file in a text editor. Perhaps just skip them?

parallel: reading inputs from standard input
thread '<unnamed>' panicked at 'index out of bounds: the len is 0 but the index is 0', src/libcollections/vec.rs:1395
note: Run with `RUST_BACKTRACE=1` for a backtrace.

Here is the backtrace:

   1:        0x106472bb3 - std::sys::imp::backtrace::tracing::imp::write::h9559bd7cb15d72ad
   2:        0x106471e2e - std::panicking::default_hook::{{closure}}::h4b3f2b69c9ce844d
   3:        0x106471118 - std::panicking::rust_panic_with_hook::h8e6300d8e8aca457
   4:        0x106470c9f - std::panicking::begin_panic::h08622fbe5a379aac
   5:        0x106470c12 - std::panicking::begin_panic_fmt::ha00d3aa9db91f578
   6:        0x10647ee0e - core::panicking::panic_fmt::h58d018e87f211baf
   7:        0x10647ec8c - core::panicking::panic_bounds_check::h38556703686d76f6
   8:        0x106461b50 - parallel::execute::command::get_command_output::h8ee21c4e00fb97ba
   9:        0x10644371e - <F as alloc::boxed::FnBox<A>>::call_box::hf3a07f776cd4b0bc
  10:        0x10647cd38 - std::sys::imp::thread::Thread::new::thread_start::h80e9dc7cc1dfe0d2
  11:     0x7fff9cf859ae - _pthread_body
  12:     0x7fff9cf858fa - _pthread_start

0.8 apparently requires rust nightly to compile

At least with rust beta (as of today, 31/12/2016) parallel 0.8 fails to compile with:

 ~/Code  cargo install parallel --force                                                                                                                                                                                                  ✓
    Updating registry `https://github.com/rust-lang/crates.io-index`
   Compiling odds v0.2.25
   Compiling libc v0.2.18
   Compiling permutate v0.2.0
   Compiling num_cpus v1.2.0
   Compiling nodrop v0.1.8
   Compiling arrayvec v0.3.20
   Compiling parallel v0.8.0
error[E0554]: #[feature] may not be used on the beta release channel
 --> /Users/timsampson/.cargo/registry/src/github.com-1ecc6299db9ec823/parallel-0.8.0/src/main.rs:4:1
  |
4 | #![feature(loop_break_value)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0554]: #[feature] may not be used on the beta release channel
 --> /Users/timsampson/.cargo/registry/src/github.com-1ecc6299db9ec823/parallel-0.8.0/src/main.rs:5:1
  |
5 | #![feature(alloc_system)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors

error: failed to compile `parallel v0.8.0`, intermediate artifacts can be found at `/var/folders/k8/92852d8j4qb73d8ch8dzd61c0000gn/T/cargo-install.tyeFy6E9fPpF`

Might be worth mentioning that in the readme

Update benchmarks

cb908eb introduced a 3.75x time regression on my system; the benchmark results are now misleading 😄.

Mimic GNU Parallel's behavior regarding failing jobs

From my testing, parallel does not have the same behavior as GNU Parallel when some of the jobs fail:

justinas@js:~$ /usr/bin/parallel false ::: a b c; echo $?
3
justinas@js:~$ ~/bin/parallel false ::: a b c; echo $?
0

That is, GNU Parallel will return a non-zero status code indicating how many jobs have failed, while mmstick/parallel will return 0 even if some jobs fail. Returning a proper status code on failure would be a useful addition for scripting scenarios.

This behavior is documented in GNU Parallel's man page:

EXIT STATUS
       If --halt-on-error 0 or not specified:

       0     All jobs ran without error.

       1-253 Some of the jobs failed. The exit status gives the number of failed jobs

       254   More than 253 jobs failed.

       255   Other error.

       If --halt-on-error 1 or 2: Exit status of the failing job.

--pipe option

I'd like to use parallel to speed up some filters that take their input via stdin

see gnu parallel --pipe

Why is parallel so slow for me?

d33tah@d33tah-pc:/tmp$ cat /tmp/test.sh 
#!/bin/bash

export LC_ALL=C

for i in `seq 3`; do

    yes "banana" | dd count=$(( 10 ** $i )) > /tmp/yes2

    time /usr/bin/parallel                --pipe cat </tmp/yes2 >/dev/null
    time /home/d33tah/.cargo/bin/parallel --pipe cat </tmp/yes2 >/dev/null

    echo

done
d33tah@d33tah-pc:/tmp$ bash /tmp/test.sh 
10+0 records in
10+0 records out
5120 bytes (5.1 kB, 5.0 KiB) copied, 0.000121935 s, 42.0 MB/s

real    0m0.185s
user    0m0.140s
sys     0m0.032s

real    0m0.145s
user    0m0.040s
sys     0m0.240s

100+0 records in
100+0 records out
51200 bytes (51 kB, 50 KiB) copied, 0.000211743 s, 242 MB/s

real    0m0.125s
user    0m0.088s
sys     0m0.024s

real    0m1.348s
user    0m0.344s
sys     0m2.632s

1000+0 records in
1000+0 records out
512000 bytes (512 kB, 500 KiB) copied, 0.00160011 s, 320 MB/s

real    0m0.134s
user    0m0.100s
sys     0m0.016s

real    0m13.676s
user    0m3.236s
sys     0m26.820s

Feature Request: joblog option

This would reproduce the --joblog feature seen in current versions of GNU Parallel.

Handy for troubleshooting or for tasks that otherwise require information on the exit values of tasksrun via Parallel

parallel multiple orders of magnitude slower than gnu parallel

the test below are with 10 000 iterations, too few to see a gain with gnu parallel or rust parallel but it shows the difference between them

I also piped the output to less rather than /dev/null; around 4500 entries, less displays the message "waitng for input"

The test uses --pipe and -q, which perform as expected. I tested the output on a smaller input set

without parallelization

seq 10000 | time -v piper --global hi blue '\d+' red > /dev/null
Command being timed: "piper --global hi blue \d+ red"
User time (seconds): 0.06
System time (seconds): 0.00
Percent of CPU this job got: 94%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.07
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 7884
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 1123
Voluntary context switches: 1
Involuntary context switches: 2
Swaps: 0
File system inputs: 0
File system outputs: 0
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

gnu parallel

seq 10000 | time -v parallel -q --pipe piper --global hi blue '\d+' red > /dev/null
Command being timed: "parallel -q --pipe piper --global hi blue \d+ red"
User time (seconds): 0.15
System time (seconds): 0.01
Percent of CPU this job got: 94%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.18
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 16448
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 18527
Voluntary context switches: 137
Involuntary context switches: 31
Swaps: 0
File system inputs: 0
File system outputs: 1544
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

rust parallel, check Minor (reclaiming a frame) page faults

seq 10000 | time -v rust-parallel -q --pipe piper --global hi blue '\d+' red > /dev/null
Command being timed: "rust-parallel -q --pipe piper --global hi blue \d+ red"
User time (seconds): 116.85
System time (seconds): 9.37
Percent of CPU this job got: 600%
Elapsed (wall clock) time (h:mm:ss or m:ss): 0:21.02
Average shared text size (kbytes): 0
Average unshared data size (kbytes): 0
Average stack size (kbytes): 0
Average total size (kbytes): 0
Maximum resident set size (kbytes): 7024
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 9793578
Voluntary context switches: 71623
Involuntary context switches: 65275
Swaps: 0
File system inputs: 0
File system outputs: 176
Socket messages sent: 0
Socket messages received: 0
Signals delivered: 0
Page size (bytes): 4096
Exit status: 0

hugepage info

cat /sys/kernel/mm/transparent_hugepage/enabled
always [madvise] never

Support '-k' (or other method of outputting processes as they finish)

At the moment mmstick-parallel has two method of outputting:

  1. Default: Output jobs in original order.
  2. --ungroup: Just dump output as it arrives.

It would be nice to have an inbetween option -- output only complete jobs, but in whatever order they finish. This is the default of gnu-parallel, and the mmstick-parallel default is '-k'. I actually don't mind the default changing, but it's nice to have a way to see jobs as they finish, in case some job hangs, meaning I never see the rest of the finished jobs.

Treat each line from stdin or from file list as one argument and use --colsep to split this in multiple arguments if requested.

Treat each line from stdin or from file list as one argument and use --colsep to split this in multiple arguments if requested.

The current implementation is different from GNU parallel.
Currently each line is split on whitespace.
This leads to unexpected results, as filenames with for example spaces are split in multiple arguments like seen in issue #57

The default argument separator when reading from a file or stdin should be "\n", this should be overridable (like the -0 optiion in GNU parallel) like requested in issue #59

# Input arguments
$ printf '1  2  3\n4\n5\n6  7\n'
1  2  3
4
5
6  7

# GNU Parallel (uses whole line as 1 argument: double spaces).
$ printf '1  2  3\n4\n5\n6  7\n' | parallel 'echo {}'
1  2  3
4
5
6  7

# GNU Parallel (split 1 line on colsep to use as different arguments: single space).
$ printf '1  2  3\n4\n5\n6  7\n' | parallel --colsep ' ' 'echo {}'
1 2 3
4
5
6 7

# mmstick parallel (splits line automatically in different arguments:  single space)
$ printf '1 2 3\n4\n5\n6 7\n' | target/x86_64-unknown-linux-musl/release/parallel 'echo {}'
ion: /sys/kernel/mm/transparent_hugepage/enabled is set to always instead of madvise. This will gravely effect the performance of Parallel.
parallel: reading inputs from standard input
1 2 3
4
5
6 7

GNU parallel --colsep option:

       --colsep regexp
       -C regexp
                Column separator. The input will be treated as a table with regexp separating the columns. The n'th
                column can be access using {n} or {n.}. E.g. {3} is the 3rd column.
                --colsep implies --trim rl.
                regexp is a Perl Regular Expression: http://perldoc.perl.org/perlre.html

Performs slower than GNU parallel when transparent huge pages are enabled

The benchmark in README.md as of version 0.5.0 claims time 0:04 for Rust parallel vs 0:54 for GNU parallel. However, this benchmark is misleading because the command line used is completely useless:

seq 1 10000 | time -v parallel echo > /dev/null would never print anything because it lacks parameter substitution. The correct command that actually does something would be seq 1 10000 | time -v parallel echo '{}' > /dev/null

On my machine Rust parallel measures 1:02 vs 0:33 for GNU parallel for the actually useful command.

Feature request: Command queue via file

Sample use case:

A file containing nuanced/complex commands (e.g.):

cat commands.list

echo "one" && du -hcs ./one
echo "two" && du -hcs ./two
echo "three" && du -hcs ./three

To be executed in parallel like so:

parallel < commands.list

This would reproduce a useful command-line behavior similar to what's found in recent version of GNU Parallel.

As a work-around, perhaps there's a way to do this in the current version using an alternate syntax?

Can't build from cargo

I install rust from homebrew, went into a empty directory and tried to install with cargo:

~/temp ❯❯❯ cargo install --git https://github.com/mmstick/parallel
    Updating git repository `https://github.com/mmstick/parallel`
error: multiple packages with binaries found: generate-files, libc-test, parallel

Not sure what I'm doing wrong?

Output isn't idempotent

Hi,

since the readme states you want to "copy" gnu parallel to some extend and I didn't find a TODO list I thought I create an issue for my observation.

When I run gnu parallel on a set of files I get an ordered and idempotent list of files.
Running your version leaves me with a (sort of) random list after every run.

Keep up the good work!

Regards
Malte

GNU parallel's --no-notice

Some build scripts [1] use parallel with --no-notice [2], which disables the citation printed out to STDERR. parallel (rust) does not include any such citation; it does however exit on receiving a bad flag, this aborts the script even though parallel (rust) can continue fine while ignoring this flag.

I suggest that parallel (rust) silently ignore this flag to be compatible with GNU parallel's usage in scripts such as this.

  1. https://github.com/adapta-project/adapta-gtk-theme/blob/1048a2873b9a9b8fe816ffe50391689da3a0c012/gtk/Makefile.am#L892
  2. https://lists.gnu.org/archive/html/parallel/2013-11/msg00006.html

Name improvement

Hi Michael

I have looked at rust-parallel. I am impressed with the speed and see there is a niche which is well filled by rust-parallel that GNU Parallel is likely never to fill.

However, calling the program 'parallel' may lead to problems you are not aware of. GNU Parallel was started before there was a UNIX tool called 'parallel'. Unfortunately another tool was later distributed as 'parallel', and that has lead to confusions that haunts us even today. The other tool was of course incompatible with GNU Parallel, but people thought they had installed GNU Parallel and were frustrated when the examples did not work. You can read more about that situation on https://www.gnu.org/software/parallel/history.html

The problem would be smaller if rust-parallel was 100% option compatible with GNU Parallel, and that it could serve as a drop-in replacement, but already now I can see rust-parallel does something different when running:

parallel echo ::: a b c :::+ 1 2 3 ::: d e f :::+ 4 5 6
parallel -n 2 echo ::: a b c d
parallel --shellquote ::: '*#"'

and I find it highly improbable that you will ever implement the '{= perl expression =}' replacement string:

parallel echo '{= $_ > 2 ? $_=">2" : $_-- =}' ::: 1 2 3 4

Walking through GNU Parallel's tutorial with rust-parallel is also impossible.

On top of this the name clash makes it hard to have both tools installed: Maybe some users like the short startup time that rust-parallel provides for some tasks, while they like the flexibilty of GNU Parallel for others? By using the same name you are making it harder for them to use both GNU Parallel and rust-parallel.

Because of these issues I will be really happy if you change the name 'parallel', as I think in the long term you will avoid creating problems for users where none need be.

I understand you are making the tool to show off what you can do with Rust. Maybe you could show Rust directly in the name? Rust-parallel, rustpar, pa(r)rust?

Do not get me wrong. I am flattered by the imitation and I like competition: A lot of the ideas in GNU Parallel came from other tools, and I hope that rust-parallel will come up with new game-changing ideas, as that will benefit society.

-q to quote the input

in command: piper --global hi blue '\d+' red

'\d' needs to be quadruple quote as in this example:
time seq 20 | rust-parallel 'echo {} | piper --global hi blue '\\d+' red'

FYI, gnu parallel needed the \ to be doubled or -q option to be used

Reading from stdin doesn't dispatch to shell

~/p/r/parallel ❯❯❯ echo 'echo 1; echo 2;' | gnu-parallel
2
~/p/r/parallel ❯❯❯ echo 'echo 1; echo 2;' | target/debug/parallel
1; echo 2;

Worse (for me)

~/p/r/parallel ❯❯❯ echo '( cd mydir; echo 2; )' | gnu-parallel
2
~/p/r/parallel ❯❯❯ echo '( cd mydir; echo 2; )' | target/debug/parallel
< just hangs forever >

This might be an intentional difference from gnu parallel? I like the fact I can put any arbitrarily complex shell command into the stdin, so I can make subshells, change directories, etc.

can't "cargo install parallel"

Both the latest release and the master branch fail to build.

$ cargo install parallel
    Updating registry `https://github.com/rust-lang/crates.io-index`
 Downloading parallel v0.6.5
 Downloading permutate v0.1.3
   Compiling permutate v0.1.3
   Compiling odds v0.2.25
   Compiling libc v0.2.18
   Compiling num_cpus v1.2.0
   Compiling nodrop v0.1.8
   Compiling arrayvec v0.3.20
   Compiling parallel v0.6.5
error[E0554]: #[feature] may not be used on the stable release channel
 --> .cargo/registry/src/github.com-1ecc6299db9ec823/parallel-0.6.5/src/main.rs:3:1
  |
3 | #![feature(alloc_system)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

error: failed to compile `parallel v0.6.5`, intermediate artifacts can be found at `/tmp/cargo-install.0fNbtHtRHfKF`

Caused by:
  Could not compile `parallel`.

To learn more, run the command again with --verbose.
$ git clone https://github.com/mmstick/parallel
[...]
$ cd parallel
$ cargo build --release
    Updating registry `https://github.com/rust-lang/crates.io-index`
 Downloading permutate v0.2.0
 Downloading arrayvec v0.3.20
 Downloading num_cpus v1.2.0
 Downloading nodrop v0.1.8
 Downloading odds v0.2.25
 Downloading libc v0.2.18
   Compiling odds v0.2.25
   Compiling libc v0.2.18
   Compiling permutate v0.2.0
   Compiling num_cpus v1.2.0
   Compiling nodrop v0.1.8
   Compiling arrayvec v0.3.20
   Compiling parallel v0.6.5 (file:///home/steven/Development/parallel)
error[E0554]: #[feature] may not be used on the stable release channel
 --> src/main.rs:3:1
  |
3 | #![feature(alloc_system)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to previous error

error: Could not compile `parallel`.

To learn more, run the command again with --verbose.
$ cargo --version
cargo 0.15.0-dev (298a0127 2016-12-20)
$ rustc --version
rustc 1.14.0

I'm a Rust newbie so I don't know how to contribute a fix for the issue.

thread 'main' panicked at 'index out of bounds: the len is 4096 but the index is 4096',

What happened here?

$  yes | dd count=1000 | RUST_BACKTRACE=1 /home/d33tah/.cargo/bin/parallel --pipe cat >/dev/null
parallel: reading inputs from standard input
1000+0 przeczytanych recordów
1000+0 zapisanych recordów
512000 bajtów (512 kB, 500 KiB), 0.0347608 s, 14.7 MB/s
thread 'main' panicked at 'index out of bounds: the len is 4096 but the index is 4096', /home/d33tah/.cargo/registry/src/github.com-1ecc6299db9ec823/parallel-0.11.3/src/input_iterator/iterator.rs:211:9
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
             at /checkout/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:49
   1: std::sys_common::backtrace::_print
             at /checkout/src/libstd/sys_common/backtrace.rs:71
   2: std::panicking::default_hook::{{closure}}
             at /checkout/src/libstd/sys_common/backtrace.rs:60
             at /checkout/src/libstd/panicking.rs:380
   3: std::panicking::default_hook
             at /checkout/src/libstd/panicking.rs:396
   4: std::panicking::rust_panic_with_hook
             at /checkout/src/libstd/panicking.rs:611
   5: std::panicking::begin_panic_new
             at /checkout/src/libstd/panicking.rs:553
   6: std::panicking::begin_panic_fmt
             at /checkout/src/libstd/panicking.rs:521
   7: rust_begin_unwind
             at /checkout/src/libstd/panicking.rs:497
   8: core::panicking::panic_fmt
             at /checkout/src/libcore/panicking.rs:92
   9: core::panicking::panic_bounds_check
             at /checkout/src/libcore/panicking.rs:68
  10: parallel::main
  11: __rust_maybe_catch_panic
             at /checkout/src/libpanic_unwind/lib.rs:98
  12: std::rt::lang_start
             at /checkout/src/libstd/panicking.rs:458
             at /checkout/src/libstd/panic.rs:361
             at /checkout/src/libstd/rt.rs:59
  13: __libc_start_main
  14: _start

Buggy behaviour when working with accentuated characters

When working with filenames containing accentuated or weird characters, the {} is not replaced correctly.

For exemple:
seq 1 10 | parallel echo "Québec-q{}.webm"

gives:

Québec-1}.webm
Québec-2}.webm
Québec-3}.webm
Québec-4}.webm
Québec-5}.webm
Québec-6}.webm
Québec-7}.webm
Québec-8}.webm
Québec-9}.webm
Québec-10}.webm

instead of Québec-q1.webm and so on.

If there's more non-ascii characters, the program segfault:

seq 1 10 | RUST_BACKTRACE=1 parallel echo "Œuf_échaudé-q{}.webm"

gives

parallel: reading inputs from standard input
thread 'main' panicked at 'byte index 18 is not a char boundary; it is inside 'é' (bytes 17..19) of `echo Œuf_échaudé-q{}.webm`', /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libcore/str/mod.rs:1771
stack backtrace:
   1:     0x560b9875899a - std::sys::imp::backtrace::tracing::imp::write::h9c41d2f69e5caabf
                        at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libstd/sys/unix/backtrace/tracing/gcc_s.rs:42
   2:     0x560b98757cee - std::panicking::default_hook::{{closure}}::hcc803c8663cda123
                        at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libstd/panicking.rs:351
   3:     0x560b98756fdb - std::panicking::rust_panic_with_hook::hffbc74969c7b5d87
                        at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libstd/panicking.rs:367
                        at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libstd/panicking.rs:555
   4:     0x560b98756b3f - std::panicking::begin_panic::hc4c5d184a1e3fb7c
                        at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libstd/panicking.rs:517
   5:     0x560b98756ac9 - std::panicking::begin_panic_fmt::h34f5b320b0f94559
                        at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libstd/panicking.rs:501
   6:     0x560b98765956 - core::panicking::panic_fmt::h1016b85b51d1931f
                        at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libstd/panicking.rs:477
   7:     0x560b98766e4f - core::str::slice_error_fail::h02b27cb27b0f1c1d
                        at /buildslave/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libcore/str/mod.rs:1771
   8:     0x560b9875069f - parallel::main::h6c96215d2b4b63a7
   9:     0x560b9875334f - main
  10:     0x7f1a66c82400 - __libc_start_main
  11:     0x560b9871d649 - _start
  12:                0x0 - <unknown>

Input token {N.} doesn't remove extension

Giving parallel a spin and trying out the example commands. I believe that the input token {N.} doesn't do what it's supposed to do:

% parallel echo {} {1} {2} {3.} ::: 1 2 file.mkv
1 1 2 . 3
2 1 2 . 3
file.mkv 1 2 . 3

If I read the description correctly, instead of seeing . 3 I should see file?

% parallel --version
MIT/Rust Parallel 0.10.7

Cannot Install on OSX

This is with rustup to the nightlies:

       Fresh libc v0.2.19
       Fresh odds v0.2.25
       Fresh gcc v0.3.41
       Fresh itoa v0.1.1
       Fresh permutate v0.2.0
       Fresh smallvec v0.3.1
       Fresh num_cpus v1.2.1
       Fresh time v0.1.36
       Fresh wait-timeout v0.1.3
       Fresh nodrop v0.1.8
       Fresh arrayvec v0.3.20
       Fresh sys-info v0.4.1
   Compiling parallel v0.10.4 (file:///Users/rjones/Sources/parallel)
     Running `rustc src/main.rs --crate-name parallel --crate-type bin -g -C metadata=f391bbe94dd644fb --out-dir /Users/rjones/Sources/parallel/target/debug --emit=dep-info,link -L dependency=/Users/rjones/Sources/parallel/target/debug/deps --extern wait_timeout=/Users/rjones/Sources/parallel/target/debug/deps/libwait_timeout-9b7fc49455ddb026.rlib --extern smallvec=/Users/rjones/Sources/parallel/target/debug/deps/libsmallvec-7e2f316ec392a6d4.rlib --extern itoa=/Users/rjones/Sources/parallel/target/debug/deps/libitoa-58ab3e11c7b36cd3.rlib --extern permutate=/Users/rjones/Sources/parallel/target/debug/deps/libpermutate-3f2228c4f25d0e98.rlib --extern time=/Users/rjones/Sources/parallel/target/debug/deps/libtime-bcc5484ee52ec8cd.rlib --extern arrayvec=/Users/rjones/Sources/parallel/target/debug/deps/libarrayvec-caf4a6c5f0300bbd.rlib --extern sys_info=/Users/rjones/Sources/parallel/target/debug/deps/libsys_info-21f1d2bc2fd2d7d0.rlib --extern num_cpus=/Users/rjones/Sources/parallel/target/debug/deps/libnum_cpus-86764cdeac0ab7b8.rlib -L native=/Users/rjones/Sources/parallel/target/debug/build/sys-info-b457c890656629ac/out`
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `file`
  --> src/execute/receive.rs:48:65
   |
48 |             if let Ok(file) = File::open(&$stdout_path) { break file }
   |                                                                 ^^^^

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `file`
  --> src/execute/receive.rs:53:65
   |
53 |             if let Ok(file) = File::open(&$stderr_path) { break file }
   |                                                                 ^^^^

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `file`
  --> src/execute/receive.rs:48:65
   |
48 |             if let Ok(file) = File::open(&$stdout_path) { break file }
   |                                                                 ^^^^

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `file`
  --> src/execute/receive.rs:53:65
   |
53 |             if let Ok(file) = File::open(&$stderr_path) { break file }
   |                                                                 ^^^^

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `file`
  --> src/execute/receive.rs:48:65
   |
48 |             if let Ok(file) = File::open(&$stdout_path) { break file }
   |                                                                 ^^^^

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `file`
  --> src/execute/receive.rs:53:65
   |
53 |             if let Ok(file) = File::open(&$stderr_path) { break file }
   |                                                                 ^^^^

error: aborting due to 6 previous errors

error: Could not compile `parallel`.

Caused by:
  process didn't exit successfully: `rustc src/main.rs --crate-name parallel --crate-type bin -g -C metadata=f391bbe94dd644fb --out-dir /Users/rjones/Sources/parallel/target/debug --emit=dep-info,link -L dependency=/Users/rjones/Sources/parallel/target/debug/deps --extern wait_timeout=/Users/rjones/Sources/parallel/target/debug/deps/libwait_timeout-9b7fc49455ddb026.rlib --extern smallvec=/Users/rjones/Sources/parallel/target/debug/deps/libsmallvec-7e2f316ec392a6d4.rlib --extern itoa=/Users/rjones/Sources/parallel/target/debug/deps/libitoa-58ab3e11c7b36cd3.rlib --extern permutate=/Users/rjones/Sources/parallel/target/debug/deps/libpermutate-3f2228c4f25d0e98.rlib --extern time=/Users/rjones/Sources/parallel/target/debug/deps/libtime-bcc5484ee52ec8cd.rlib --extern arrayvec=/Users/rjones/Sources/parallel/target/debug/deps/libarrayvec-caf4a6c5f0300bbd.rlib --extern sys_info=/Users/rjones/Sources/parallel/target/debug/deps/libsys_info-21f1d2bc2fd2d7d0.rlib --extern num_cpus=/Users/rjones/Sources/parallel/target/debug/deps/libnum_cpus-86764cdeac0ab7b8.rlib -L native=/Users/rjones/Sources/parallel/target/debug/build/sys-info-b457c890656629ac/out` (exit code: 101)

I get the same error compiling local source and from cargo install parallel.

Change in behaviour of --max-args

In version 0.10 the upper first is seen, in version 0.11 the second one. I find the first one more useful and intuitive. From a quick look here, I could not find out why this was changed.

The old behaviour parses multiple args as individual arguments passed to the program, while the new behaviour passes it as a single long space-separated argument.

[0] bushart@Colossus07 ~/home $ parallel -n5 'cat {}' ::: 1 2 3 4 5
cat: 1: No such file or directory
cat: 2: No such file or directory
cat: 3: No such file or directory
cat: 4: No such file or directory
cat: 5: No such file or directory

[0] bushart@Colossus07 ~/home $ parallel -n5 'cat {}' ::: 1 2 3 4 5
cat: 1 2 3 4 5: No such file or directory

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.