A Shell Tricks: Search and Replace

A Shell Tricks: Search and Replace
Photo by Heliberto Arias / Unsplash

It's easy to use VS Code to search and replace text entries. Yet, mass file renaming is a fairly common task, especially when you move Ansible inventories or other artifacts across environments.

Let's assume there is some host naming convention that allows you to make an educated guess with a glance at the host's name. For example, something like rhl-stg-itdweb01.mydomain.com gives you a pretty good idea of the OS, environment, department, and primary function.  

To move your scripts from staging to the production system, you should update text and filenames to keep the Ansible inventory coherent.

Typically, I start with the mass file rename. The example below gives you an idea of producing a new name from the old one.

$ for f in *-stg-*; do nf=$(echo $f|sed "s/-stg-/-prd-/"); mv $f $nf; done
Single Line that renames files by the rules.

Let's expand this cryptic charm to a human-readable block of code below.

# For all files that match *-stg-* mask dp
for f in *-stg-*; do
#       inline command that translates all '-stg-' entries into '-prd-'   
  nf=$(echo $f | sed "s/-stg-/-prd-/")
# Rename file using original and new name   
  mv $f $nf
# Done with this one, iterate next if available.   
done  
Command explained.
If you want to be on the safe side, replace mv with cp and preserve the original files until you make all the changes. 

The next step is to update the content of the files and substitute all staging references with the production ones.

$ sed -i "s/-stg-/-prd-/g" *-prd-* 
Replace all stg entries with prd ones. 

There are a few notes regarding sed processing instructions:

  • The argument "-i" instructs sed to make in-place changes. Without this argument, the sed prints out results to the standard output as in the first command.
  • You may notice a subtle difference in the search and replacement instructions for files and content. The latter one ends up with the "/g" which stands for"global." It may have no much sense for file names, but should always be used to replace all entries in the file body.
  • Most of the time, we use "/" as an argument separator, but any non-space character will work just fine. My second choice is '#', and commands "s/abs/cde/g" and "s#abs#cde#g"  are identical.