# Discarding the output of a process

**URL:** <https://discourse.haskell.org/t/discarding-the-output-of-a-process/11689>\
**Category:** Learn\
**Created:** [March 22, 2025, 8:11pm UTC](https://discourse.haskell.org/t/discarding-the-output-of-a-process/11689 "2025-03-22T20:11:42Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![mpilgrem](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/mpilgrem/32/2529_2.png) [@mpilgrem](https://discourse.haskell.org/u/mpilgrem)\
**Post date:** [March 22, 2025, 8:11pm UTC](https://discourse.haskell.org/t/discarding-the-output-of-a-process/11689/1 "2025-03-22T20:11:42Z")

</div>

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):

```haskell
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:

```haskell
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.

---

<div class="post-metadata">

**Author:** ![Bodigrim](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/bodigrim/32/1457_2.png) [@Bodigrim](https://discourse.haskell.org/u/Bodigrim)\
**Post date:** [March 22, 2025, 10:38pm UTC](https://discourse.haskell.org/t/discarding-the-output-of-a-process/11689/2 "2025-03-22T22:38:51Z")

</div>

It seems to be an intentional change between [0.1.3.0](https://hackage.haskell.org/package/open-browser-0.1.3.0/src/lib/Web/Browser/Linux.hs) and [0.1.4.0](https://hackage.haskell.org/package/open-browser-0.1.4.0/src/lib/Web/Browser/Linux.hs).

One potential difference between `foo` and `sh -c foo` is that in the second case `foo` is not necessarily an executable, but could be a shell command or a shell alias, but I struggle to see how it could be relevant for `xdg-open`.

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [March 22, 2025, 11:32pm UTC](https://discourse.haskell.org/t/discarding-the-output-of-a-process/11689/3 "2025-03-22T23:32:02Z")

</div>

I think one other difference is that it now expands environment variables like `$HOME`.

---

<div class="post-metadata">

**Author:** ![mpilgrem](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/mpilgrem/32/2529_2.png) [@mpilgrem](https://discourse.haskell.org/u/mpilgrem)\
**Post date:** [March 23, 2025, 4:36pm UTC](https://discourse.haskell.org/t/discarding-the-output-of-a-process/11689/4 "2025-03-23T16:36:45Z")

</div>

Thanks for the responses! In addition, @atravers has suggested avoiding Haskell’s garbage collection (GC) as a possible motive for using the shell. (GHC’s GC has moved on since the summer of 2015.)

A copy of the original (now deleted) repository suggests that the motivation for introducing the shell was ‘Silence xdg-open; Fixes [now lost] #7’. As it was introduced only for (chatty) `xdg-open` (Linux, BSD) and not (taciturn) `open` (macOS), it appears to me that the author’s own motivation was not shell expansion of environment variables.

EDIT: It turns out that `xdg-open` is not an application but a shell script (one that starts with a shebang - `#!/bin/sh`).
