Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error-...
#5: Post edited
- I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error--.
- But I don't find a way to do it. So far, I've written this:
- ```bash
- alx@devuan:~/tmp/g$ ls
- file file2 script
- alx@devuan:~/tmp/g$ cat file
- foo
- bar
- alx@devuan:~/tmp/g$ cat file2
- qwe
- xcsv
- ```
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ echo foo | bash script; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ echo bar | bash script; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 1
- ```
- If find(1) fails, it uses the trap handler set next to grep(1), probably because pipes are executed in parallel, and because lastpipe makes the trap(1) be executed in the same shell.
- If I change the script to not use lastpipe, then that is fixed (find(1) errors are properly transformed into code 2), but then when grep(1) doesn't find anything it also is treated as an error with code 2.
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- #shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 2
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 2
- ```
- Is there a way to set different traps for different parts of a pipeline?
Alternatively, I guess I could entirely disable `set -Ee`, and inspect PIPESTATUS for each command, but I was hoping for something simpler.
- I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error--.
- But I don't find a way to do it. So far, I've written this:
- ```bash
- alx@devuan:~/tmp/g$ ls
- file file2 script
- alx@devuan:~/tmp/g$ cat file
- foo
- bar
- alx@devuan:~/tmp/g$ cat file2
- qwe
- xcsv
- ```
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ echo foo | bash script; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ echo bar | bash script; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 1
- ```
- If find(1) fails, it uses the trap handler set next to grep(1), probably because pipes are executed in parallel, and because lastpipe makes the trap(1) be executed in the same shell.
- If I change the script to not use lastpipe, then that is fixed (find(1) errors are properly transformed into code 2), but then when grep(1) doesn't find anything it also is treated as an error with code 2.
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- #shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 2
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 2
- ```
- Is there a way to set different traps for different parts of a pipeline?
- Alternatively, I guess I could entirely disable `set -Ee`, and inspect PIPESTATUS for each command, but I was hoping for something simpler. Also, the real script is much more complex, and I think PIPESTATUS would be impractical, so I'd probably fall back to `grep || true` and say my script also returns 0 if nothing matched, unlike grep(1).
#4: Post edited
- I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error--.
- But I don't find a way to do it. So far, I've written this:
- ```bash
- alx@devuan:~/tmp/g$ ls
- file file2 script
- alx@devuan:~/tmp/g$ cat file
- foo
- bar
- alx@devuan:~/tmp/g$ cat file2
- qwe
- xcsv
- ```
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ echo foo | bash script; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ echo bar | bash script; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 1
- ```
- If find(1) fails, it uses the trap handler set next to grep(1), probably because pipes are executed in parallel, and because lastpipe makes the trap(1) be executed in the same shell.
- If I change the script to not use lastpipe, then that is fixed (find(1) errors are properly transformed into code 2), but then when grep(1) doesn't find anything it also is treated as an error with code 2.
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- #shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 2
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 2
- ```
- Is there a way to set different traps for different parts of a pipeline?
Alternatively, I guess I could entirely disable `set -Ee` in that part of the script, and inspect PIPESTATUS for each command, but I was hoping for something simpler.
- I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error--.
- But I don't find a way to do it. So far, I've written this:
- ```bash
- alx@devuan:~/tmp/g$ ls
- file file2 script
- alx@devuan:~/tmp/g$ cat file
- foo
- bar
- alx@devuan:~/tmp/g$ cat file2
- qwe
- xcsv
- ```
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ echo foo | bash script; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ echo bar | bash script; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 1
- ```
- If find(1) fails, it uses the trap handler set next to grep(1), probably because pipes are executed in parallel, and because lastpipe makes the trap(1) be executed in the same shell.
- If I change the script to not use lastpipe, then that is fixed (find(1) errors are properly transformed into code 2), but then when grep(1) doesn't find anything it also is treated as an error with code 2.
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- #shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 2
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 2
- ```
- Is there a way to set different traps for different parts of a pipeline?
- Alternatively, I guess I could entirely disable `set -Ee`, and inspect PIPESTATUS for each command, but I was hoping for something simpler.
#3: Post edited
- I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error--.
- But I don't find a way to do it. So far, I've written this:
- ```bash
- alx@devuan:~/tmp/g$ ls
- file file2 script
- alx@devuan:~/tmp/g$ cat file
- foo
- bar
- alx@devuan:~/tmp/g$ cat file2
- qwe
- xcsv
- ```
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ echo foo | bash script; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ echo bar | bash script; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 1
- ```
- If find(1) fails, it uses the trap handler set next to grep(1), probably because pipes are executed in parallel, and because lastpipe makes the trap(1) be executed in the same shell.
- If I change the script to not use lastpipe, then that is fixed (find(1) errors are properly transformed into code 2), but then when grep(1) doesn't find anything it also is treated as an error with code 2.
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- #shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 2
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 2
- ```
Is there a way to untrap only part of a pipe?- Alternatively, I guess I could entirely disable `set -Ee` in that part of the script, and inspect PIPESTATUS for each command, but I was hoping for something simpler.
- I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error--.
- But I don't find a way to do it. So far, I've written this:
- ```bash
- alx@devuan:~/tmp/g$ ls
- file file2 script
- alx@devuan:~/tmp/g$ cat file
- foo
- bar
- alx@devuan:~/tmp/g$ cat file2
- qwe
- xcsv
- ```
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ echo foo | bash script; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ echo bar | bash script; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 1
- ```
- If find(1) fails, it uses the trap handler set next to grep(1), probably because pipes are executed in parallel, and because lastpipe makes the trap(1) be executed in the same shell.
- If I change the script to not use lastpipe, then that is fixed (find(1) errors are properly transformed into code 2), but then when grep(1) doesn't find anything it also is treated as an error with code 2.
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- #shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 2
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 2
- ```
- Is there a way to set different traps for different parts of a pipeline?
- Alternatively, I guess I could entirely disable `set -Ee` in that part of the script, and inspect PIPESTATUS for each command, but I was hoping for something simpler.
#2: Post edited
- I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error--.
- But I don't find a way to do it. So far, I've written this:
- ```bash
- alx@devuan:~/tmp/g$ ls
- file file2 script
- alx@devuan:~/tmp/g$ cat file
- foo
- bar
- alx@devuan:~/tmp/g$ cat file2
- qwe
- xcsv
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- alx@devuan:~/tmp/g$ echo foo | bash script; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ echo bar | bash script; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 1
- ```
- If find(1) fails, it uses the trap handler set next to grep(1), probably because pipes are executed in parallel, and because lastpipe makes the trap(1) be executed in the same shell.
- If I change the script to not use lastpipe, then that is fixed (find(1) errors are properly transformed into code 2), but then when grep(1) doesn't find anything it also is treated as an error with code 2.
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- #shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 2
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 2
- ```
- Is there a way to untrap only part of a pipe?
- Alternatively, I guess I could entirely disable `set -Ee` in that part of the script, and inspect PIPESTATUS for each command, but I was hoping for something simpler.
- I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error--.
- But I don't find a way to do it. So far, I've written this:
- ```bash
- alx@devuan:~/tmp/g$ ls
- file file2 script
- alx@devuan:~/tmp/g$ cat file
- foo
- bar
- alx@devuan:~/tmp/g$ cat file2
- qwe
- xcsv
- ```
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ echo foo | bash script; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ echo bar | bash script; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 1
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 1
- ```
- If find(1) fails, it uses the trap handler set next to grep(1), probably because pipes are executed in parallel, and because lastpipe makes the trap(1) be executed in the same shell.
- If I change the script to not use lastpipe, then that is fixed (find(1) errors are properly transformed into code 2), but then when grep(1) doesn't find anything it also is treated as an error with code 2.
- ```bash
- alx@devuan:~/tmp/g$ cat script
- #!/bin/bash
- set -Eeuo pipefail;
- #shopt -s lastpipe;
- trap 'exit 2;' ERR;
- if test -z "$*"; then
- trap 'exit 1' ERR;
- grep foo;
- else
- find "$@" -type f \
- | {
- trap 'exit 1' ERR;
- xargs grep foo;
- };
- fi;
- ```
- ```bash
- alx@devuan:~/tmp/g$ bash script file; echo $?
- foo
- 0
- alx@devuan:~/tmp/g$ bash script file2; echo $?
- 2
- alx@devuan:~/tmp/g$ bash script file3; echo $?
- find: ‘file3’: No such file or directory
- 2
- ```
- Is there a way to untrap only part of a pipe?
- Alternatively, I guess I could entirely disable `set -Ee` in that part of the script, and inspect PIPESTATUS for each command, but I was hoping for something simpler.
#1: Initial revision
How to pipe grep(1) and use compatible exit codes?
I need to wrap grep(1) in a script, and I'd like the script to have an exit code compatible with that of grep(1) --that is, it should return 0 if it found something, 1 if it didn't, and 2 on error--.
But I don't find a way to do it. So far, I've written this:
```bash
alx@devuan:~/tmp/g$ ls
file file2 script
alx@devuan:~/tmp/g$ cat file
foo
bar
alx@devuan:~/tmp/g$ cat file2
qwe
xcsv
alx@devuan:~/tmp/g$ cat script
#!/bin/bash
set -Eeuo pipefail;
shopt -s lastpipe;
trap 'exit 2;' ERR;
if test -z "$*"; then
trap 'exit 1' ERR;
grep foo;
else
find "$@" -type f \
| {
trap 'exit 1' ERR;
xargs grep foo;
};
fi;
alx@devuan:~/tmp/g$ echo foo | bash script; echo $?
foo
0
alx@devuan:~/tmp/g$ echo bar | bash script; echo $?
1
alx@devuan:~/tmp/g$ bash script file; echo $?
foo
0
alx@devuan:~/tmp/g$ bash script file2; echo $?
1
alx@devuan:~/tmp/g$ bash script file3; echo $?
find: ‘file3’: No such file or directory
1
```
If find(1) fails, it uses the trap handler set next to grep(1), probably because pipes are executed in parallel, and because lastpipe makes the trap(1) be executed in the same shell.
If I change the script to not use lastpipe, then that is fixed (find(1) errors are properly transformed into code 2), but then when grep(1) doesn't find anything it also is treated as an error with code 2.
```bash
alx@devuan:~/tmp/g$ cat script
#!/bin/bash
set -Eeuo pipefail;
#shopt -s lastpipe;
trap 'exit 2;' ERR;
if test -z "$*"; then
trap 'exit 1' ERR;
grep foo;
else
find "$@" -type f \
| {
trap 'exit 1' ERR;
xargs grep foo;
};
fi;
alx@devuan:~/tmp/g$ bash script file; echo $?
foo
0
alx@devuan:~/tmp/g$ bash script file2; echo $?
2
alx@devuan:~/tmp/g$ bash script file3; echo $?
find: ‘file3’: No such file or directory
2
```
Is there a way to untrap only part of a pipe?
Alternatively, I guess I could entirely disable `set -Ee` in that part of the script, and inspect PIPESTATUS for each command, but I was hoping for something simpler.
