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.
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):
date > date.txt(the first pipeline/command in your command list) is parsed by Bash, withdate.txtbeing created/clobbered;dateis executed, with itsstdoutwritten todate.txt;- If
datereturns 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, withdate.txtclobbered; cut -d " " -f 1is executed with a now emptydate.txtasstdin, thestdoutof 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.txtmay be more readable, if not also more shell-portable ascut -d ' ' -f 1 < date.txt >> date.txt(single quotes rather than double as you’re not requesting any content interpolation).- Consider using
set -o noclobberorset -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