Why does using `cat` with `head` fail in strict mode?

0
2
Asked By CuriousCoder42 On

I've been using "strict mode" in my bash scripts for a few weeks now and it's generally been positive. However, I'm confused about a specific issue that arises when I use `cat`. Here's a snippet of my script:

```bash
#!/bin/bash

trap 'echo "ERROR: A command has failed. Exiting the script. Line was ($0:$LINENO): $(sed -n "${LINENO}p" "$0")"; exit 3' ERR
set -Eeuo pipefail

set -x
du -a /etc > /tmp/etc-files 2>/dev/null || true

ls -lh /tmp/etc-files

# works (without cat)
head -n 10 > /tmp/disk-usage-top-10.txt /tmp/disk-usage-top-10.txt

echo "done"
```

Can someone help me understand why this happens?

4 Answers

Answered By StrictModeFan On

Just a heads-up, strict mode can definitely introduce these types of problems. It's a common issue that people run into, and while it helps catch errors, it can also complicate things unnecessarily. You’re not alone in finding it a bit tricky!

Answered By ScriptGuru33 On

Just a tip on script formatting: it looks like there are issues in how you displayed your shell script. You might want to format it properly with four spaces before each line to make it easier to read, especially when you share it in forums.

For example:
```
#!/bin/bash
echo "This is code!"
```

Answered By TechWhiz99 On

The issue stems from how `cat` and `head` interact through a pipe. When `head` finishes reading its 10 lines, it exits, which triggers a SIGPIPE signal to `cat`. This causes `cat` to terminate as well, since it thinks its reader is gone and treats it as an error due to strict mode. It's possible it didn't break before because `cat` managed to finish writing before `head` completed, but with larger outputs, it can fail. This could be one of those quirkier cases of strict mode throwing up flags where it usually wouldn’t. Just be aware that with `pipefail`, the termination is treated as significant, unlike default behavior where it generally goes unnoticed.

BashBuster21 -

That’s really interesting! I get how piped commands could cause synchronization issues, but why is it that `head` isn't able to read everything from `cat` before it exits? Seems like a common usage.

Answered By ScriptingSage10 On

Have you thought about simplifying your command? Instead of relying on `cat`, you could do something like this:

`du -a /etc | head -n 10 > /tmp/disk-usage-top-10.txt`

If you need that intermediate file for any reason, you could also use:

`du -a /etc | tee -a /tmp/etc-files >(head -n 10 > /tmp/disk-usage-top-10.txt)`

FileFinder99 -

Yes, I see your point! The sorting is missing, though—this was just a minimal example I provided.

Related Questions

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.