Strawberry
Strawberry

Reputation: 67918

Why might this cause the file to be empty?

TMP="$$.FILE"

#Process puts contents into TMP

cat "$TMP" | sort |  head > "$TMP"

I already made sure the file was not empty to begin with. Without the > "$TMP", it outputs something, but when its stored again into the same file, its empty. What might be the cause?

Upvotes: 1

Views: 201

Answers (3)

wilhelmtell
wilhelmtell

Reputation: 58685

The last pipe will truncate the file which the first pipe reads, before anything really happens. So what happens is cat tries to read a file which the call to head immediately truncated. This is the causing the issues here; the > operator is a shell operator which means "truncate this file right away and then have the process write its standard output into the file.

On a related note, you don't need cat here.

Try this instead:

TMP="$$.FILE"    
sort <"$TMP" | head > "$TMP.tmp"
mv "$TMP.tmp" "$TMP"

Upvotes: 1

John Kugelman
John Kugelman

Reputation: 361849

You cannot write to and read from a file at the same time. Here is roughly what happens:

  1. > "$TMP" causes file to be opened for writing, which also truncates the file.
  2. cat "$TMP" reads from now blank file.
  3. File stays empty.

Commands that purport to modify a file in place in fact perform a bit of temp file shuffling under the covers. For example, sed -i will process an input file and save the results to input.tmp, then do mv input.tmp input at the end to overwrite the original. You should follow that model.

Upvotes: 3

nobody
nobody

Reputation: 20174

Those processes all get run in parallel, so the head command is truncating the file before cat has a chance to read it.

To get the result you want, you need to write the sort output to a different file then move that over the original.

cat "$TMP" | sort | head > "$TMP".new
mv "$TMP".new "$TMP"

Upvotes: 2

Related Questions