Search code examples
command-line-interfacezsh

Find and remove a character in subdirectory names recursively with find, sed and mv


I am trying to remove a character in subdirectories recursively but can't seem to nail the correct answer. I am running BSD and would like to achieve this with find, sed and mv. I am a beginner in scripting and in the use of sed so any help would be appreciated.

I have directories named in different subdirectories

dir/foobar 01
    foobar 02
    foobar 03
dir2/foobar 01
     foobar 02
     foobar 03

I want to remove the 0 in every directory name

dir/foobar 1
    foobar 2
    foobar 3
dir2/foobar 1
     foobar 2
     foobar 3

I have gotten this far with find and sed but don't know how incorporate the mv command

find . -type d -name "foobar 01" | sed 's/0//g'

This prints the right reformat but without the mv command it doesn't do anything further...

Is there a way to do this with one command for all matching subdirs or do I have to go each case seperately?

Thank you.


Solution

  • Since you are using zsh you can use recursive globs.

    Given:

    % tree .
    .
    ├── dir
    │   ├── foobar 01
    │   ├── foobar 02
    │   ├── foobar 03
    │   └── foobar 4
    └── dir2
        ├── foobar 01
        ├── foobar 02
        ├── foobar 03
        └── foobar 2
    
    11 directories, 0 files
    

    You can use this recursive glob to find the directories with 0 in the name and rename them. This also tests if the renaming would erase an existing file or directory:

    #!/bin/zsh
    # ^ that path deponds on your system.
    
    for fn in **/*0[0-9]*/; do
        nfn="${fn//0}"
        if [[ -e $nfn ]]; then  
            echo "$nfn already exists! NOT renaming $fn=>$nfn"
            continue 
        fi     
        echo "renaming: $fn=>$nfn"
        mv "$fn" "$nfn"
    done    
    

    Result:

    % tree .
    .
    ├── dir
    │   ├── foobar 1
    │   ├── foobar 2
    │   ├── foobar 3
    │   └── foobar 4
    └── dir2
        ├── foobar 02
        ├── foobar 1
        ├── foobar 2
        └── foobar 3
    
    11 directories, 0 files
    

    The same script works with Bash if you add shopt -s globstar above the loop.