Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Combination of cut and redirection did not write to file?

I wrote the date to a file using below command

$ date > date.txt 
# Sun Jul 24 14:16:43 +08 2022

Now I would like to replace all texts in date.txt to be left with Sun only, solely using redirection and cut command, so below is my attempt

$ date > date.txt && cut < date.txt -d " " -f 1 > date.txt

Using the command above, date.txt will become empty instead of having Sun in the file.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

However, if instead of overwriting the file, we append to the file, it will work

$ date > date.txt && cut < date.txt -d " " -f 1 >> date.txt
# Sun

Any idea why?

UPDATES

I’ve also verified that the same command will be working fine if we are writing to another file instead, like below

$ date > date.txt && cut < date.txt -d " " -f 1 > anotherFile.txt
# Sun

But I would like to understand how the data flow works, why "output" of the cut command will be missing if coming from and going to the same file

>Solution :

When Bash encounters a clobbering redirection request (e.g., > [file]), the file is created/clobbered by Bash before the command itself executes. As such, date > date.txt && cut < date.txt -d " " -f 1 > date.txt breaks down as follows (with relevant detail):

  1. date > date.txt (the first pipeline/command in your command list) is parsed by Bash, with date.txt being created/clobbered;
  2. date is executed, with its stdout written to date.txt;
  3. If date returns zero (i.e., was successful), cut < date.txt -d " " -f 1 > date.txt (the second pipeline/command in your command list) is parsed by Bash, with date.txt clobbered;
  4. cut -d " " -f 1 is executed with a now empty date.txt as stdin, the stdout of which is also empty.

Your >> date.txt version works because Bash isn’t first clobbering date.txt, it’s opening it for appending. In general, command < [infile] > [outfile] should almost always involve distinct files for these reasons.

Two other suggestions, if you don’t mind:

  • cut < date.txt -d " " -f 1 >> date.txt may be more readable, if not also more shell-portable as cut -d ' ' -f 1 < date.txt >> date.txt (single quotes rather than double as you’re not requesting any content interpolation).
  • Consider using set -o noclobber or set -C (equivalent) for your Bash sessions and scripts. It’s often a helpful and revealing safety mechanism to have in place.

The following sections of the Bash manpage may be helpful:

  • SHELL GRAMMAR: Simple Commands
  • SHELL GRAMMAR: Pipelines
  • SHELL GRAMMAR: Lists
  • REDIRECTION
  • REDIRECTION: Redirecting Input
  • REDIRECTION: Redirecting Otuput
  • REDIRECTION: Appending Redirected Output
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading