xdg-open on debian 9 fails to open browser

@user310685 got it close - but DEFINITELY WRONG. That fix "works" only when xdg-open is NOT given "naked" file paths (i.e. with no leading "file://" URI scheme and double-slash) or file-schemed URI's (i.e. with the leading "file://"). Those two types of argument should have xdg-open defer to pcmanfm, but they won't.

The actual error is not a mistake in the STDERR redirection. Rather, it's that the script writer confused the test "and" operator and the shell's process list "and" connector. The one (erroneously) used is "-a"; the correct one is "&&".

As reference, I've reproduced the original script line, my fix for that line, and the "horror of horrors" suggestion by @user310685:

#ORIG#   if pcmanfm --help >/dev/null 2>&1 -a is_file_url_or_path "$1"; then
#FIXED#  if pcmanfm --help >/dev/null 2>&1 && is_file_url_or_path "$1"; then
#HORROR# if pcmanfm --help >/dev/null 2>$1 -a is_file_url_or_path "$1"; then

The intention of the if ..; then is given in the script line just above it:

# pcmanfm only knows how to handle file:// urls and filepaths, it seems.

With this comment in mind, the way to understand the problematic if .. then line is:

  1. Test if pcmanfm is runnable (by having it report it's own help, and discarding any STDOUT or STDERR)
  2. AND, run the script-function is_file_url_or_path() to then see if the "$1" argument is acceptable to pcmanfm (as per the code comment noted above)

If both these conditions hold, then the script flows into a short block that:

  1. Calls the script-function file_url_to_path() to strip off any leading "file://" part (as local var file)
  2. If the result is NOT an absolute path (i.e. doesn't start with "/"), then prepend the CWD to the value of file
  3. Execute pcmanfm "$file"

Why the Original Script Fails:

As noted above, the script is (erroneously) using "-a" as a "process list and operator." What actually happens is that the shell runs the command (after STDOUT and STDERR redirections are "pulled out" of the command, which are allowed to be anywhere in the command word sequence after the first word):

pcmanfm --help -a is_file_url_or_path "$1"

This always succeeds (unless pcmanfm isn't executable on the PATH). All the extra stuff on the command line (-a ..) is ignored by pcmanfm running it's --help mode. Thus, the "process as a file or file-URL" code block is always executed. When given an URL (with a scheme part), the file_url_to_path() script-function only removes a leading "file://", truncates any trailing "#..." fragment, and also URI-decodes the argument (i.e. "%XX" are converted to ASCII). NOTE: Unless the argument starts with "file:///", nothing is done.

For example, the OP's URL "https://www.google.com" is unchanged by file_url_to_path() since it does not begin with "file:///". BUT later code then considers this argument to be a "relative path" since it clearly doesn't start with "/". Thus, it prepends the CWD as described and then pcmanfm is almost certainly NOT going to find that munged value as an extant path to display. Instead, it shows an error pop-up, as in the OP's question.

The Fix:

Simple enough: use the correct syntax for a process chain AND-operator: "&&" as shown in the #FIXED# line, above.

The HORROR of @user310685's Suggestion:

What @user310685 proposes does fix one problem, sort of. What happens is that the shell dutifully does variable expansion and then attempts to execute something like:

pcmanfm --help >/dev/null 2>https://www.google.com -a is_file_url_or_path https://www.google.com

This, is almost certainly going to produce a shell redirection error (unless the CWD has a folder (in the right place) named "https:" - which it could). That redirection error spits a message to STDERR, and then the shell moves on. Since this error occured within an if .. else .. fi block, the shell takes the else .. fi part, which is what @user310685 wants. Thus, the problem is solved...

BUT AT WHAT COST???

There are two problems with this not-quite-right fix:

  1. When actually given a path or a file-schemed URL, the wrong code path is executed (the else .. fi part). This is because the intended process chain is really only a single process that (almost) always generates a shell redirection error which is taken as the if .. ; condition as being "false." This not soooo bad, since that else .. fi block merely defers work to another script-function called open_generic() which is designed to handle paths and file-URL's (but not using pcmanfm to do the work, rather some other complex code-path that I didn't analyze but I presume does a fair job). But WAIT! The HORROR...
  2. Look back up at the pcmanfm --help ... expanded script line that the shell attempts. Note the redirection of STDERR. Consider what happens if this is done with a legitimate path, like "/home/user/precious". OMG The attept to probe if pcmanfm is available and then to test if the argument is a file just OVERWROTE THE FILE!!! Bye-bye precious...

This for Debian 10 (buster), LXDE and xdg-utils 1.1.3-1 too. There is a typo in the xdg-open script and the solution is as follows:

    --- /usr/bin/xdg-open   2018-05-20 00:18:48.000000000 +0200
+++ /home/klaumi/bin/xdg-open   2018-09-13 15:15:51.630704599 +0200
@@ -928,7 +928,7 @@
 {

     # pcmanfm only knows how to handle file:// urls and filepaths, it seems.
-    if pcmanfm --help >/dev/null 2>&1 -a is_file_url_or_path "$1"; then
+    if pcmanfm --help >/dev/null 2>$1 -a is_file_url_or_path "$1"; then
         local file="$(file_url_to_path "$1")"

         # handle relative paths

(Note that & in 2>&1 has to be replaced with $)