Execute a command for each file in a directory recursively on Linux

I recently wanted to make a change — actually a string replacement — in every file in the current directory and all directories beneath it, perhaps filtering by file extension. In this case, I wanted to change four spaces to a tab character in every .php source file. I created a small BASH shell script file to do this, though you could also just run the command directly at the command line:

find . -type f -name '*.php' -exec sed -i 's/    /\t/g' {} \;

Explanation:

  • find lists all files, one per line, in the current directory and all subdirectories recursively
  • . (period) means current directory
  • -type f only list files, not directories.
  • -name ‘*.php’ only if the name matches * (wildcard) with “.php” at the end
  • -exec execute the following command for each result that matched
  • sed -i ‘s/    /\t/g’ replace, or substitute, one string for another. I’m searching for four consecutive spaces and replacing with t, meaning tab character. the /g at the end means global, replace each instance wherever it may appear in the file on each line. -i means “edit file in place” so the modified file is saved back to itself.
  • {} this inputs the file for the sed command
  • \; I think this finishes the -exec parameter for find. Don’t forget the backslash

To change spaces to tabs or tabs to spaces, you can also look into the expand and unexpand commands.

Overall I highly recommend learning the sed command for quick and easy find & replace operations in text files.

More examples of the find command with -exec:

Delete all directories matching a name, such as CVS, under the current directory:

cd /path/to/myproject/directory/src
find . -type d -name 'CVS' -exec rm -rf {} \;