Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Running an external command with parentheses as arguments

I’ve got a bash command that works:

find content/posts \( -iname '*.jpg' \) -print0 | xargs -0 -P8 -n2 mogrify -auto-orient

I’m trying to convert it into a Rust command:

let mut cmd = Command::new("/usr/bin/find")
        .args([
                post.dest_dir(&dest_dir).as_os_str().to_str().unwrap(),
                "(-iname '*.jpg')",
                "-print0",
        ])
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

let output = Command::new("/usr/bin/xargs")
        .args(["-0", "-P8", "-n2", "mogrify", "-auto-orient"])
        .stdin(cmd.stdout.take().unwrap())
        .output()
        .unwrap_or_else(|e| panic!("failed to execute process: {}", e));

However I’m getting the following output:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

find: (-iname '*.jpg'): No such file or directory
exit code: exit status: 1

mogrify: no decode delegate for this image format `' @ error/constitute.c/ReadImage/741.
mogrify: no decode delegate for this image format `MD' @ error/constitute.c/ReadImage/741.

mogrify: insufficient image data in file `content/posts/2021-06-26-united-states/DSCF1507.JPG' @ error/jpeg.c/ReadJPEGImage_/1120.

It appears to be reading the right directory but it’s not respecting the pattern passed to find \( -iname '*.jpg' \) and including markdown files.

Is there a proper way to pass those arguments into Command?

>Solution :

Two rules will make this work:

  1. Everything that’s space-separated in the original bash command needs to be passed as a separate argument.

  2. Quoting with ' and escaping with \ are shell syntax that don’t need to be carried over to the Rust version.

You can also use post.dest_dir(&dest_dir) directly by passing it in a separate .arg() call. This gets rid of the string conversions and the possibility of failure if the path is not valid UTF-8.

let mut cmd = Command::new("/usr/bin/find")
    .arg(post.dest_dir(&dest_dir))
    .args(["(", "-iname", "*.jpg", ")", "-print0"]);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading