2

I have folders and files with the following structure and some of the files contains the string ModuleName.

ModuleName
├── Application\ Logic
│   └── Interactor
│       ├── ModuleNameInteractor.swift
│       └── ModuleNameInteractorIO.swift
├── Module\ Interface
│   └── IModuleNameModule.swift
└── User\ Interface
    ├── Presenter
    │   └── ModuleNamePresenter.swift
    ├── View
    │   ├── IModuleNameView.swift
    │   └── ModuleNameViewController.swift
    └── Wireframe
        └── ModuleNameWireframe.swift

I want to replace all the occurrences of ModuleName in folder name, file name and file content by another name (let's say TestModule) with a Linux or a python script.

I tried with the find command but renaming the folders provoque No such file or directory for the subfolders / subfiles.

Morniak
  • 958
  • 1
  • 12
  • 37
  • Can you say little bit more about `"I want to replace all the occurrences of ModuleName in ... file content"` – Vor Jun 30 '14 at 16:04
  • For example, the file `ModuleNameInteractor.swift` contain the following code `class ModuleNameInteractor : ModuleNameInteractorInput` and after executing the script, I want to get `class TestModuleInteractor : TestModuleInteractorInput` – Morniak Jun 30 '14 at 16:08

2 Answers2

3

I'd use sed -i (in-place replace) for the content replacements, and a find|while read loop for the renames.

Here's the BSD sed (standard on Macs) version:

find . -type f -exec sed -e s/ModuleName/TestModule/g -i '' '{}' ';'
find . -depth -name '*ModuleName*' -print0|while IFS= read -rd '' f; do mv -i "$f" "$(echo "$f"|sed -E 's/(.*)ModuleName/\1TestModule/')"; done

And here's GNU sed:

find . -type f -exec sed -e s/ModuleName/TestModule/g -i '{}' ';'
find . -depth -name '*ModuleName*' -print0|while IFS= read -rd '' f; do mv -i "$f" "$(echo "$f"|sed -r 's/(.*)ModuleName/\1TestModule/')"; done

The extra details in the while read are to correctly handle arbitrary filenames -- names with spaces and other odd characters. Some quick testing suggests that zsh read can now handle null-terminated strings properly; if you have issues, try running it in bash instead.

Aaron Davies
  • 1,190
  • 1
  • 11
  • 17
  • I have modified the commands to work in mac (`find . -type f -name '*ModuleName*' -exec sh -c 'mv "$0" "${0/ModuleName/Test}"' '{}' \; find . -name '*ModuleName*' -print0|while IFS= read -rd '' f; do mv -i "$f" "${f//ModuleName/Test}"; done`) but I got errors :http://0bin.net/paste/Fp4Vo46LzuXC5Q0f#XSc1UBdGOwnJ1YpgdCmafXDe-XqLC67MBd+RA+B168m (sed replace the first occurrence in the path). – Morniak Jul 02 '14 at 07:59
  • I've edited it to give what I hope is a correct Mac version, and also to fix a bug--my original rename logic failed to account for the fact that the directory got renamed first, so after the first mv, the files were no longer reachable by their original path. The fix is to replace them from the bottom up (`find -depth`), changing only the *last* occurrence of `ModuleName` in each path each time. – Aaron Davies Jul 02 '14 at 21:51
  • It works perfectly, thank you ! On OSX I have this error message `sed: RE error: illegal byte sequence` but the solution can be found here http://stackoverflow.com/questions/19242275/re-error-illegal-byte-sequence-on-mac-os-x – Morniak Jul 03 '14 at 08:00
  • I assume the error is in the first statement, the `sed -i`? Do you know what character encoding the files you're editing are in? – Aaron Davies Jul 04 '14 at 03:36
0

After trying to fight with the terminal, I found out that the Massreplaceit app available for free here can handle this problem very easily

PS : I am not working there !

Stanislas Heili
  • 295
  • 2
  • 10