0

This will be better explained with an example. I'm building a little bash script that reruns the passed commandline every 1 second. this is my first attempt:

-- file wtbash

watch -n1 "$@"

If I issue:

wt "df -h | grep sda"

It works ok. I want to be able to do:

wt df -h | grep sda

And to work just the same

That is, I want to treat "df -h | grep sda" as a single string param

opensas
  • 60,462
  • 79
  • 252
  • 386
  • 1
    I suppose you're looking for: `"$*"` All arguments as a single string, but you'll have to escape the `|` or the shell will interpret it instead of passing it to your script. – Ondrej K. Mar 24 '19 at 14:53
  • 1
    At the very least, you *must* quote the `|` to prevent the shell from parsing this as two commands. If you do that, you may as well quote *everything* and pass a single string to `wt`, in which case you may as well *also* just write `watch -n1 "$1"`. – chepner Mar 24 '19 at 14:58
  • See [Bash FAQ 050](https://mywiki.wooledge.org/BashFAQ/050), "I'm trying to put a command in a variable, but the complex cases always fail!". – chepner Mar 24 '19 at 15:00
  • The duplicate *question* is not a precise duplicate, but the answers definitely apply equally to both quoting and wildcard expansion. – tripleee Mar 24 '19 at 15:00

1 Answers1

3

There's an app a variable for that! From man bash:

   *      Expands to the positional parameters, starting from one.  When the expan‐
          sion is not within double quotes, each positional parameter expands to  a
          separate  word.   In contexts where it is performed, those words are sub‐
          ject to further word splitting and pathname expansion.  When  the  expan‐
          sion  occurs  within  double quotes, it expands to a single word with the
          value of each parameter separated by the first character of the IFS  spe‐
          cial  variable.   That  is, "$*" is equivalent to "$1c$2c...", where c is
          the first character of the value of the IFS variable.  If IFS  is  unset,
          the  parameters  are separated by spaces.  If IFS is null, the parameters
          are joined without intervening separators.

So change your script to:

#!/bin/bash

watch -n1 "$*"

But that won't work for pipes. You will still need to escape those:

wt df -h \| grep sda
terdon
  • 3,260
  • 5
  • 33
  • 57
  • great, any tip on how to escape them from the bash script itself? – opensas Mar 24 '19 at 14:57
  • 1
    You *can't*. It has to be escaped from the *calling* script so that the `|` is passed to your script in the first place. – chepner Mar 24 '19 at 14:59
  • 1
    @opensas what chepner said. The pipe needs to be escaped before the script ever sees it. This is handled by the shell calling the script and not by the script itself. – terdon Mar 24 '19 at 14:59