I am seeking advice about the best way to discard the output of a process.
On Linux and BSD, package open-browser uses the xdg-open application script but discards its output. It does that with something that looks like this (the code comments document my understanding of what is going on):
openBrowser url =
-- sh -c '...'
--
-- tells the shell (sh) to execute the given string as a command, and
-- the following argument (url) is passed as a positional argument $0.
--
-- xdg-open "$0" 2>&1 > /dev/null
--
-- The $0 is expanded and the double quotes ensures it is treated as a single
-- argument to xdg-open.
--
-- 2>&1 redirects standard error to standard output.
--
-- > /dev/null discards standard output.
openBrowserWith "sh" ["-c", "xdg-open \"$0\" 2>&1 > /dev/null", url]
(openBrowserWith is a helper function that makes use of withCreateProcess.)
What I am wondering is why the original author made use of the sh shell (in July 2015, when GHC 7.10.1 was the latest thing) and did not just obtain, and then discard, the output from xdg-open in Haskell.
Is it possible to reason that one approach is to be preferred over the other?
EDIT: I’ve subsequently discovered§ that the shell approach discards the output of xdg-open but not of the application it opens while using withCreateProcess as follows:
openBrowserSilentlyWith ::
String
-- ^ Name of relevant executable on the PATH.
-> [String]
-- ^ Arguments for executable.
-> IO Bool
openBrowserSilentlyWith cmd args =
-- /dev/null is specifc to Unix-like operating systems
withFile "/dev/null" WriteMode $ \nullHandle ->
withCreateProcess (proc cmd args)
{ std_out = UseHandle nullHandle
, std_err = UseHandle nullHandle
} $ \_ _ _ p -> (== ExitSuccess) <$> waitForProcess p
discards the output of xdg-open and the application it opens.
That is because xdg-open is not an application but a script.
§ Discovered by experimenting, as google-chrome on Ubuntu 24.02.2, via WSL2, spits out all sorts of warnings when it opens.