Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem on Linux with exif_call() #4

Closed
insilentio opened this issue Nov 3, 2021 · 5 comments
Closed

Problem on Linux with exif_call() #4

insilentio opened this issue Nov 3, 2021 · 5 comments

Comments

@insilentio
Copy link

Hi Josh
Sorry, it's me again. I am currently trying to move some picture resizing code to RStudio Workbench, which runs under Linux. I have encountered the following problem. While install_exiftool() and configure_exiftoolr() seem to work properly, exif_call() etc. do not work.

e.g.
> exif_version()
sh: 'perl' '/home/sszbad/R/x86_64-pc-linux-gnu-library/4.0/exiftoolr/exiftool/exiftool': No such file or directory
Error in system2(exiftoolpath, args = args, stdout = stdout) :
error in running command

I tried some debugging and am now somehow closer to the reason, albeit not the solution of the problem.

The test_exiftool function in configure_exiftoolr() uses system(), not system2() to run the exiftool command against the OS:
_Browse[2]> test_exiftool

function (command, quiet = TRUE) 
{
    if (!quiet) 
        message("Trying exiftool command: ", command)
    command_works <- suppressWarnings(suppressMessages(0 == try(**system**(command, 
        ignore.stdout = TRUE, ignore.stderr = TRUE, show.output.on.console = TRUE), 
        silent = TRUE)))
    if (command_works) {
        ver_string <- paste(system(command, ignore.stderr = TRUE, 
            intern = TRUE), collapse = "\n")
        ver_number <- suppressWarnings(as.numeric(ver_string))
        return(!is.na(ver_number))
    }
    else {
        return(FALSE)
    }
}

<bytecode: 0x55b476576da0>
<environment: namespace:exiftoolr>_

And this call works properly:
Browse[3]> system(command, ignore.stdout = TRUE, ignore.stderr = TRUE, show.output.on.console = TRUE)
arguments 'show.output.on.console', 'minimized' and 'invisible' are for Windows only
Browse[3]> command
[1] "'perl' '/home/sszbad/R/x86_64-pc-linux-gnu-library/4.0/exiftoolr/exiftool/exiftool' -ver"
Browse[3]> system(command)
12.34

However, exif_call() etc. seem to use system2(). Now, if I understand the differrence between system and system2 correctly, system2 does not allow args in the command call ("Unlike system, command is always quoted by shQuote, so it must be a single command without arguments.")

I believe this is the reason why it fails. The exif_call() tries to run this command:
system2(exiftoolpath, args = args, stdout = stdout)
where in my case
Browse[3]> exiftoolpath
[1] "'perl' '/home/sszbad/R/x86_64-pc-linux-gnu-library/4.0/exiftoolr/exiftool/exiftool'"

, while the same command but with system() instead of system2() works.

If I manually change the exiftoolpath above to just "perl" and add the real exiftool path to args, then the call works:
Browse[3]> system2(exiftoolpath, args = args, stdout = stdout)
[1] "12.34"
Browse[3]> exiftoolpath
[1] "perl"
Browse[3]> args
[1] "/home/sszbad/R/x86_64-pc-linux-gnu-library/4.0/exiftoolr/exiftool/exiftool"
[2] "-@"
[3] "'/tmp/RtmpI3pgul/args.cmd152c152d23795'"

I assume that the system call under Linux is behaving differently than under Win or MacOS (where I didn't found such issues).

Kind regards and sorry for the really lengthy description
Daniel

JoshOBrien added a commit that referenced this issue Nov 3, 2021
Issue #4 describes the failure of `exif_call()` on a Linux
machine. That problem results because the value of `exiftoolpath`
returned by get_exiftool_command() is of this form:

```r
"'/path/to/perl' '/path/to/exiftool'"
```

Formerly (prior to commit a24e28f on 2020-10-22), `exif_call()`
used `system(command, ...)` to launch its external call to
ExifTool. That handled an `exiftoolpath` like the one above just fine.

In commit a24e28f, `exif_call()` shifted from `system()` to
`system2(exiftoolpath, args=args, stdout=stdout)`. The switch to
`system2()` was needed because the then newly introduced
`pipeline="csv"` option needs to be able to write stdout to a file,
and `system2()` supports that, while `system()` does not.
Unfortunately, `system2()` fails with values of `exiftoolpath` like
the one above, since it only accepts a single token in the string
passed as its first argument.

This commit fixes that issue by inspecting, in
`configure_exiftoolr()`, any value of `command` that succeeded in
launching ExifTool and, if it contains more than one token, splitting
it into a character vector before passing it on. If passed a value of
`exiftoolpath` of length greater than one, `exif_call()` now passes
its first element to `system2()` as its `command=` argument, and
prepends the remaining elements to the character vector passed to its
`args=` argument.
@JoshOBrien
Copy link
Owner

@insilentio Good catch, and thanks for getting started with the debugging. I think, with cf87159, I've implemented a fix. (The commit message for 38dabad describes the underlying issue that was causing the problems you reported.)

Would you mind installing the most recent version (using devtools::install_github("JoshOBrien/exiftoolr") or otherwise), and testing on your Linux and then letting me know how it goes? If it works for you, I'll test a bit more and then push a new version to CRAN.

@insilentio
Copy link
Author

@JoshOBrien will try to do it tomorrow

@insilentio
Copy link
Author

@JoshOBrien, installed the latest version and this is working fine, thanks a lot.

@JoshOBrien
Copy link
Owner

@insilentio Super. Thanks.

@JoshOBrien
Copy link
Owner

Closed with 38dabad and cf87159.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants