2 Synthesis‎ > ‎Computing‎ > ‎Linux‎ > ‎Shell‎ > ‎


Replacing in files and in file names.

In Filenames

The rename command is useful man rename gives information.

rename -n 's/string1/string2' *

The first argument 's/string1/string2' is a Perl expression in this case it replaces string1 in the filename with string2. The -n flag stops actual renaming taking place and the command just prints what it will do if the -n flag is removed. This is good for checking before doing a big rename.

In Files

To do a bulk replace of string1 with string2 in all the files in a given filepath and below.

grep -rlZ matchstring  filepath | xargs -0 sed -i 's/string1/string2/g'

How does this work? Lets look at some excerpts from man grep.

Synopsis: grep [OPTIONS] PATTERN [FILE...]

Description: grep  searches  the  named  input FILEs (or standard input if no files are named, or if a single hyphen-minus (-) is given as file name) for lines containing a match to the given PATTERN.  By default, grep prints the matching lines.

Option: -r, --recursive Read all files under each directory, recursively, following symbolic links only if they are on the command line.

Option: -l, --files-with-matches Suppress normal output; instead print the name of each input file from which output would normally have been printed.  The file scanning will stop on the first match.

Option: -Z, --null Output  a  zero  byte  (the  ASCII NUL character) instead of the space that normally follows a file name.  For example,  grep -lZ  outputs  a  zero  byte  after each file name instead of the usual newline.  This option makes the output  unambiguous,  even in the presence of file names containing unusual characters like newlines. 

Try  grep -rlZ matchstring  filepath to see the files being found.

Now pipe to the xargs command;

grep -rlZ matchstring  filepath | xargs echo

This pipes the output into the input for xargs which then calls echo with each file name of each file containing the matchstring. Again the result is a list of file names. Lets look at an excerpts from man xargs.

Description: xargs reads items from  the  standard  input, delimited by blanks (which can be protected with double or single quotes or a backslash) or newlines, and  executes the  command following xargs one or more times with any arguments given followed by items read from standard input.  Blank  lines  on the standard input are ignored.

Option: --null, -0 Input  items  are  terminated  by a null character instead of by whitespace, and the quotes and backslash are not special  (every character is taken literally).  Disables the end of file string, which is treated like any other  argument.   Useful  when  input items  might  contain  white space, quote marks, or backslashes. The GNU find -print0 option produces  input  suitable  for  this mode.

Replace echo with sed -i 's/string1/string2/g' to get;

grep -rl matchstring  filepath | xargs -0 sed -i 's/string1/string2/g'

How does this work? Lets look at some excerpts from man sed.

Synopsis: sed [OPTION]... {script-only-if-no-other-script} [input-file]...

Description: Sed  is a stream editor.  A stream editor is used to perform basic text transformations on an input stream (a file or input from a pipeline).  While in some ways similar to an editor which permits scripted  edits  (such as  ed),  sed works by making only one pass over the input(s), and is consequently more efficient.  But it is sed's ability to filter text in a pipeline which particularly distinguishes it from other types of editors.

Option: -i edit files in place.

The 's/string1/string2/g' script means;

s/ means use / as the delimiter between string1 and string2 i.e. the delimiter must not be contained in the strings themselves. g at the end means replace all occurrences of string1 with string2, not just the first.

Hopefully that explains it.