ryan0
ryan0

Reputation: 1525

Is it possible to display a file's contents and delete that file in the same command?

I'm trying to display the output of an AWS lambda that is being captured in a temporary text file, and I want to remove that file as I display its contents. Right now I'm doing:

... && cat output.json && rm output.json

Is there a clever way to combine those last two commands into one command? My goal is to make the full combined command string as short as possible.

Upvotes: 1

Views: 478

Answers (2)

dash-o
dash-o

Reputation: 14452

For cases where

  • it is possible to control the name of the temporary text file.
  • If file is not used by other code

Possible to pass "/dev/stdout" as the.name of the output

Regarding portability: see stack exchange how portable ... /dev/stdout

POSIX 7 says they are extensions. Base Definitions,

Section 2.1.1 Requirements: The system may provide non-standard extensions. These are features not required by POSIX.1-2008 and may include, but are not limited to: [...]

• Additional character special files with special properties (for example,  /dev/stdin, /dev/stdout,  and  /dev/stderr)

Using the mandatory supported /dev/tty will force output into “current” terminal, making it impossible to pipe the output of the whole command into different program (or log file), or to use the program when there is no connected terminals (cron job, or other automation tools)

Upvotes: 2

vdavid
vdavid

Reputation: 2544

No, you cannot easily remove the lines of a file while displaying them. It would be highly inefficient as it would require removing characters from the beginning of a file each time you read a line. Current filesystems are pretty good at truncating lines at the end of a file, but not at the beginning.

A simple but extremely slow method would look like this:

while [ -s output.json ]
do
  head -1 output.json
  sed -i 1d output.json
done

While this algorithm is plain and simple, you should know that each time you remove the first line with sed -i 1d it will copy the whole content of the file but the first line into a temporary file, resulting in approximately 0.5*n² lines written in total (where n is the number of lines in your file).

In theory you could avoid this by do something like that:

while [ -s output.json ]
do
  line=$(head -1 output.json)
  printf -- '%s\n' "$line"
  fallocate -c -o 0 -l $((${#len}+1)) output.json
done

But this does not account for variable newline characters (namely DOS-formatted newlines) and fallocate does not always work on xfs, among other issues.

Since you are trying to consume a file alongside its creation without leaving a trace of its existence on disk, you are essentially asking for a pipe functionality. In my opinion you should look into how your output.json file is produced and hopefully you can pipe it to a script of your own.

Upvotes: 1

Related Questions