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:
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:
-
Everything that’s space-separated in the original bash command needs to be passed as a separate argument.
-
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"]);