pure-bash-bible
pure-bash-bible copied to clipboard
Include prepend function
hey, this is innovative and fantastic! can you explain how it works, too? looking at how to prepend stdin to file.... I find the function no workie for me
# declare -f prepend
prepend ()
{
printf '%s%s' "$1" "(< $2)" > "$2"
}
# echo world >zz
# prepend hello zz
# cat zz
hello(< zz)# bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Basically:
- Print the string that will be prepended.
- Print the contents of the file.
- Redirect this combined output to the file.
Notes:
-
$(< "$2")
is equivalent to$(cat "$2")
. - This reading and writing of the same file is safe due to the
$(< "$2")
being evaluated first. (I could be wrong here, however I don't see it working any other way).
@georgalis Hi, I've somehow missed a $
that's probably why the function didn't work for you. @dylanaraps explains the function better than I ever could.
Example use case:
Prepending the JIRA ID to the commit message within a commit hook within a prepare-commit-msg hook
https://github.com/helpermethod/awesome-git-hooks/blob/master/prepare-commit-msg.d/prepend-issue-key.sh
This reading and writing of the same file is safe due to the $(< "$2") being evaluated first. (I could be wrong here, however I don't see it working any other way).
@dylanaraps This is exactly how it works!
I would also quote the $2
inside $(< $2)
, so $(< "$2")
.
The only issue with this method is that it'll be slow for large files. bash
has to load the entire file as a string and then pass it to printf
and finally pipe
it back to the file.
I'm looking into whether or not there's a more performant method of doing this. :+1:
...yes thank you both. much improved. not sure best way for performance and to fail safely, I normally use tmp files.
my use case has a bug that doesn't preserve trailing \n,
prepend () { printf '%s%s' "$1" "$(< $2)" > "$2" ;}
seq 1 5 >zz ; echo "hello" | prepend "$(cat)" zz
in this case two \n are missing from the final file.
That is "fixable" by changing %s%s
to %s\n%s\n
though not ideal since it'll add a newline where one already exists.
yes, I started to offer that, but it also adds a newline when there shouldn't be any!
I would also quote the
$2
inside$(< $2)
, so$(< "$2")
.The only issue with this method is that it'll be slow for large files.
bash
has to load the entire file as a string and then pass it toprintf
and finallypipe
it back to the file.I'm looking into whether or not there's a more performant method of doing this. 👍
I suppose using sed
would be the most performant solution for this task.