How can I start vim by inserting the date and some text at the beginning of the file? - vim

I'm working on a bash script to create log files something like this, where the latest entry appears first in file:
2019-07-26 Looks like SSD needs replacing
2019-07-25 db backup failed
If no text is included on command line, just start vim.
If text is included on the command line, insert date and that text, e.g.
edlog db backup failed
Conceptually it looks like this in my head but only the first -c command works as expected:
!/bin/bash
if [ $# -eq 0 ]
then
nvim ~/log.txt
else
# :r will Insert date at top of file.
# $\t moves to end of line and inserts a tab
# $* appends contents of command line
nvim -c ":r! date +\%F" -c "$\t" -c "$*" ~/log.txt
fi

Here's my solution. I'm very much open to criticism and corrections.
#!/bin/bash
# Appends to a log file if you type a message, or
# just brings up vim in case you want to log several
# lines' worth
# Nothing added to command line, so just bring up vim:
if [ $# -eq 0 ]
then
nvim ~/Dropbox/log.txt
else
# User entered something like this:
# edlog Extra backup last night due to OS update
LINE=" $*"
# Format date like 07/25/2019
# Start inserting text after the date.
# Insert all arguments on command line, like "Re-test db"
# Then write out file, and quit back to shell
nvim -c ":pu=strftime('%m/%d/%Y')" -c ":startinsert!" -c "norm a$LINE" -c "wq" ~/Dropbox/log.txt
fi

A quasi-vim centric solution:
date > file
echo "$#" >>file
vim file +'0join'
Using vim commands:
vim +'0r !date' +'0d' +"normal! A<Tab>$#"
Where <Tab> is a literal tab character.
Or with ex:
ex <<EOF file
0r !date
0d
normal! A<Tab>$#
wq
EOF

Related

How can I give special command (insert) to vi?

I remember doing magic with vi by "programming" it with input commands but I don't remember exactly how.
My sepcial request are:
launch vi in a script with command to be executed.
do an insert in one file.
search for a string in the file.
use $VARIABLE in the vi command line to replace something in the command.
finish with :wq.
I my memory, I sent the command exactly like in vi and the ESC key was emulate by '[' or something near.
I used this command into script to edit and change files.
I'm going to see the -c option but for now I cannot use $VARIABLE and insert was impossible (with 'i' or 'o').
#!/bin/sh
#
cp ../data/* .
# Retrieve filename.
MODNAME=$(pwd | awk -F'-' '{ print $2 }')
mv minimod.c $MODNAME.c
# Edit and change filename into the file (from mimimod to the content of $VARIABLE).
vi $MODENAME.c -c ":1,$s/minimod/$MODNAME/" -c ':wq!'
This example is not functionning (it seems the $VARIABLE is not good in -c command).
Could you help me remember memory ;) ?
Thanks a lot.
Joe.
You should not use vi for non-interactive editing. There's already another tool for that, it's called sed or stream editor.
What you want to do is
sed -i 's/minimod/'$MODNAME'/g' $MODNAME.c
to replace your vi command.
Maybe you are looking for the ex command, that can be run non-interatively:
ex $MODENAME.c <<< "1,\$s/minimod/$MODNAME/
wq!
"
Or if you use an old shell that does not implement here strings:
ex $MODENAME.c << EOF
1,\$s/minimod/$MODNAME/
wq!
EOF
Or if you do not want to use here documents either:
echo "1,\$s/minimod/$MODNAME/" > cmds.txt
echo "wq!" >> cmds.txt
ex $MODENAME.c < cmds.txt
rm cmds.txt
One command per line in the standard input. Just remember not to write the leading :. Take a look at this page for a quick review of ex commands.
Granted, it would be better to use the proper tool for the job, that would be sed, as #IsaA answer suggests, or awk for more complex commands.

Automate a Vim script to write text to a file

I am writing a script that runs on the command line and I want to be able to automatically append some static text to a file using Vim.
This is a simplified version of what I have:
insert_text() {
vim -s ./text.txt new.txt;
}
Then it would run on the command line by typing insert_text. Inside text.txt I have tried things such as:
iSome Text:wq
This puts me in insert mode and writes the text but I don't know how to leave insert mode in this way. The :wq never works and is instead written to the new.txt.
If you just want to append text to a file you don't need any special tools. For instance you can just use:
echo "Some text" >> myfile.txt
or if you have a large block of text
>>myfile.txt cat <<EOF
some
long
block of text
EOF
If you want it at the start of a file you can use a temporary file to do this. For instance:
echo "Some Text" | cat - myfile.txt > /tmp/file && mv /tmp/file myfile.txt
This will append someText at the beginning of line 1:
vim -c "1 s/^/someText" -c "wq" test.txt
When you run a command from the terminal and you want Vim to exit after that, instead of :wq do +wq. For example:
vim +'SomeCommand' +qa

Bash script adding special characters to the end of any file I create

I am creating a bash script to create backups, however the bash scripts mkdir is naming the folder with some sort of special characters on the end. if I ls the directory the name show up with a ? on the end which I know is terminals way of showing unrecognized special characters.
How do I get my bash script to to create the folder without adding on this special unrecognized character to the end.
Any help is appreciated.
See script below:
#!/bin/bash
mkdir -p "/var/backups/Backup"
mysqldump -u user1 -ptest DB tbl1 > "/var/backups/Backup/tbl1.sql"
DAY=$(date +%Y%m%d%H%M%S)
zip -r /var/backups/bkup-$DAY.zip /var/backups/Backup
cat -A shows the following:
#!/bin/bash^M$
mkdir -p "/var/backups/Backup"^M$
mysqldump -u user1 -ptest DB tbl1 > "/var/backups/Backup/tbl1.sql"^M$
DAY=$(date +%Y%m%d%H%M%S)^M$
zip -r /var/backups/bkup-$DAY.zip /var/backups/Backup
the ^M (CR) characters in your cat -A output are the problem: the shell treats only LF as the "end of line" marker, and the preceding CR character becomes part of the previous word. only '/' and '\0' characters are forbidden in pathnames in POSIX(ish) systems.
you can fix your script with dos2unix or with
vim yourfile.sh
:set ff=unix
:wq

How do you quit without saving when using vim -c flag

I want to run something along the lines of
vim -r -c "w %.new | q!" ${filename}
However, the ! is parsed as the prefix for an external command. Similar issues happen when using single quotes.
I could work around this with the following code, but it feels much less clean or obvious than the previous code.
cp ${filename} ${filename}.new && mv .${filename}.swp .${filename}.new.swp;
vim -r -c "wq" ${filename}.new;
Use single quotes instead of double quotes. The ! is being interpreted in bash not vim.
vim -r -c 'w %.new | q!' ${filename}
! followed by test runs the last command that starts with that text. In this case bash looks for a command starting with " which isn't found. The single quotes stops bash from interpreting the !
Some examples of using ! in bash
It seems the actual problem was that %.new existed. To just force over write use w! instead of w
vim -r -c 'w! %.new | q!' ${filename}

Execute a command within Vim from the command line

Is there a way to execute a Vim command on a file from the command line?
I know the opposite is true like this:
:!python %
But what if I wanted to :retab a file without opening it in Vim? For example:
> vim myfile.c
:retab | wq
This will open myfile.c, replace the tabs with spaces, and then save and close. I'd like to chain this sequence together to a single command somehow.
It would be something like this:
> vim myfile.c retab | wq
This works:
gvim -c "set et|retab|wq" foo.txt
set et (= set expandtab) ensures the tab characters get replaced with the correct number of spaces (otherwise, retab won't work).
I don't normally use it, but vim -c ... also works
The solution as given above presumes the default tab stop of eight is appropriate. If, say, a tab stop of four is intended, use the command sequence "set ts=4|set et|retab|wq".
You have several options:
-c "commands" : will play Ex commands as you entered them in the command line.
In your example : vim myfile -c 'retab | wq'. This is what Firstrock suggested.
-S "vim source file" : will source given vim script
(like running vim -c "source 'vim source file'"):
If you have a file script.vim containing:
retab
wq
Then you can use vim myfile.c -s script.vim (the extension does not really matter)
-s "scriptin file": will play contents of file as it contains normal mode commands: If you have script.txt containing:
:retab
ZZ
with end of lines consisting of a single ^M character (for example you saved the script using the :set fileformat=mac | w), then you can run: vim myfile.c -S script.txt (ZZ is another way to exit vim and save current file).
Note that you can record those scripts with vim my_file -W script.txt, but it suffers a bug if you happen to use gvim (the GUI).
Not a direct answer to your question, but if you want to replace tabs with spaces (or do any other regex search/replace) for a list of files, you can just use in-place sed search/replace:
sed -i 's/\t/ /g' foo1.txt foo2.txt
or
ls *.txt | xargs sed -i 's/\t/ /g'
(In this example I am replacing each tab character with three spaces.)
NOTE: the -i flag means operate in-place.
From the sed man page:
-i[SUFFIX], --in-place[=SUFFIX]
edit files in place (makes backup if extension
supplied)

Resources