1

I'm trying to use an if [grep] using the exit value to trigger it

to test, from the command line

$ ls ~/dir | grep txt
$ echo $?
0

However when i use it in an if statement in a script, i.e.

if [ ls /some/dir | grep -q pattern ]; then
    echo y
fi

It says

line 1: [ missing `]' (the line the if statement was written on)

Why is this happening and is there a way to fix it?

codeforester
  • 39,467
  • 16
  • 112
  • 140
Cencoroll
  • 37
  • 1
  • 5
  • 4
    `[` is the name of a command, not part of the `if` statement's syntax. – chepner Feb 05 '20 at 19:58
  • 5
    _[Never parse `ls`](https://unix.stackexchange.com/questions/128985/why-not-parse-ls-and-what-to-do-instead)._ – Enlico Feb 05 '20 at 19:59
  • 1
    To get what you're trying to work: drop the `[]`, use `if ls /some/dir | grep -q pattern; then`. But really, you should use a glob for this: `shopt -s nullglob; f=(*txt*); if (( ${#f[@]} > 0 )); then` – Benjamin W. Feb 05 '20 at 20:01
  • 1
    BTW, what you're trying to do here in a larger sense (check whether any files match a pattern) is the subject of [BashFAQ #4](http://mywiki.wooledge.org/BashFAQ/004); the best-practice approach it teaches does not involve using `ls` *or* `grep`. – Charles Duffy Feb 05 '20 at 20:45

1 Answers1

1

That is because [ is and conditional expression, check the details.

You should use () instead:

if (ls /some/dir | grep -q pattern); then
    echo y
fi
Juan P. Osio
  • 475
  • 1
  • 3
  • 9
  • 3
    Do not use the parens either. They make your code slower / less efficient than just leaving them out would be, as in `if ls /some/dir | grep -q pattern; then` – Charles Duffy Feb 05 '20 at 20:42
  • 2
    (the performance hit is because in shell, parens aren't just grouping; they tell the shell to fork off an additional subprocess and run the enclosed code inside it. Sure, pipes also require forking and so does execution of external commands, so it's not a fork-vs-no-fork decision here, but you're potentially creating one more fork than there would be otherwise, depending on how efficient the particular shell executing this code happens to be). – Charles Duffy Feb 05 '20 at 20:44
  • 2
    Moreover, the best practices for checking whether any files in a directory have names patching a pattern -- as taught in [BashFAQ #4](http://mywiki.wooledge.org/BashFAQ/004) -- do not involve *either* `ls` or `grep`; details of why parsing `ls` output is an antipattern are discussed in [ParsingLs](https://mywiki.wooledge.org/ParsingLs). – Charles Duffy Feb 05 '20 at 20:46