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.