GiselleSerate / myaliases

Useful shell aliases and functions.
6 stars 1 forks source link

prepending .included line into .bash_aliases #72

Closed aryarm closed 5 years ago

aryarm commented 6 years ago

It might be better for setup to prepend the code that includes .included, instead of appending it. That way, other aliases and things that are defined in the user's .bash_aliases will be given priority over our own. This will also allow people to build their own aliases over our own (or generally write any code that depends on ours).

aryarm commented 6 years ago

It might be hard to find a portable way of prepending the text without creating a temporary file. Oh, how I love bash

sources: some recommendations for prepending text and a discussion about portability

GiselleSerate commented 6 years ago

What? could have sworn sed could handle this, it's a text editor like any other

aryarm commented 6 years ago

yeah, but sed -i isn't very portable, apparently we can use sed -i's backup file feature: sed -i.bak -e '…' SOMEFILE as described in this stack overflow post but this won't work on some systems (ex: BusyBox) and isn't really in POSIX and apparently there are sometimes problems with permissions on the files?

GiselleSerate commented 6 years ago

Wait, so are we not supposed to use sed or just one particular feature?

aryarm commented 6 years ago

just sed -i, I think

aryarm commented 6 years ago

I know this is an old issue but I kept it in the back of my mind. How's this for a one-line, portable solution?!

echo "$(echo "prepend me" | cat - .bash_aliases)" > .bash_aliases

The subshell forces bash to execute the cat before setting up the redirect into the file (source). Using cat - will force cat to accept input from stdin, so we can use it to concatenate stdin with the .bash_aliases file. A variable could also be used in place of the string. It seems better than the solutions on StackOverflow, at least. We don't use temporary files and it's completely portable to my knowledge.

I suppose you could also use process substitution instead of the pipe. But process substitution is a bashism, so it's not portable.

echo "$(cat <(echo "prepend me") .bash_aliases)" > .bash_aliases

Alternatively, you could use a here-string instead of using echo. But again, here-strings are a bashism, so it's not portable. One benefit to this method over the other two, however, is that it doesn't create any nested subshells:

echo "$(cat - .bash_aliases <<< "prepend me")" > .bash_aliases
aryarm commented 5 years ago

Fun fact that I recently discovered:

Running cat without specifying its input will cause it to block and read input from the terminal (until you press Ctrl+D). Here's an example where someone used it to append arbitrary text to a file.

Turns out you can prepend arbitrary text to a file using this method, too :D echo "$(cat - filename)" > filename