I was recently faced with the situation of having to edit 44 similar files, and do a lot of manipulations on them. The same manipulation for each file. Sounds like a lot of monkey work, so I made a script for this using bash and vim for some parts.
Let's imagine we want to remove a single line from each file. This line is identified by it containing the word
for file in directory/*; do
vim "$file" -s <(echo -e "/foo/\ndd\n:wq")
Done! Wait, what happened here?!?
Let's go through it step by step:
- We iterate over the files, this is pretty basic bash stuff.
- We open the file in vim.
-s flag tells vim to use the file following the flag as a the user input. The commands are run in normal mode, so you can navigate around the file, etc., normally.
<(command arg0 arg1) is a special syntax of bash that creates a temporary in-memory file descriptor, so instead of specifying an actual input file, you can generate the contents of the file. This can also be useful for complex multi-stream situations, but here we just want to inline our commands instead of creating a separate script file.
echo -e prints the text we give it with proper treatment for special characters.
/foo/ jumps to the first occurrence of
dd deletes the line under the cursor, so because we jumped to the first occurrence of foo, it deletes the line that had the string
:wq Saves the file and quits vim.
That's all there is to it! Hope you find some use for this!
NOTE: You will probably want to have a clean HEAD in your source control before doing this, or otherwise backups. There's a lot of things that can go wrong here, e.g. if the file doesn't contain foo, the first line is deleted instead.