Rename the sub-sub-directories of a directory named _QWE

I can run a command in all directories named _QWE using:

find . -name '_QWE' -type d -execdir touch {}/1234.txt ;

However, I need to run -execdir rename 's!^./(d+ -)s(d+.)!$1!' {} ; in all the immediate sub-directories of _QWE to rename the sub-directories of the sub-directories of _QWE.

I mean suppose I have a directory structure like:

├── folder_1
│   └── _QWE
│       ├── Course 1
│       │   ├── 1 - Introduction
│       │   ├── 2 - 1. Basics of Course 1
│       │   ├── 3 - 2. Conclusion of Course 1
│       ├── Course 2
│       │   ├── 1 - Introduction
│       │   ├── 2 - 1. Basics of Course 2
│       │   ├── 3 - 2. Conclusion of Course 2
├── folder_2
│   └── folder_3
│      └── _QWE
│          ├── Course X1
│          │   ├── 1 - Introduction
│          │   ├── 2 - 1. Basics of Course X1
│          │   ├── 3 - 2. Conclusion of Course X1
│          ├── Course X2
│          │   ├── 1 - Introduction
│          │   ├── 2 - 1. Basics of Course X2
│          │   ├── 3 - 2. Conclusion of Course X2

Here I want to rename:

1 - Introduction
2 - 1. Basics of Course 1
3 - 2. Conclusion of Course 1
1 - Introduction
2 - 1. Basics of Course 2
3 - 2. Conclusion of Course 2
1 - Introduction
2 - 1. Basics of Course X1
3 - 2. Conclusion of Course X1
1 - Introduction
2 - 1. Basics of Course X2
3 - 2. Conclusion of Course X2

Here for example, 3 - 2. Conclusion of Course X2 will be renamed to 3 - Conclusion of Course X2. This is what 's!^./(d+ -)s(d+.)!$1!' does.

Just to be clear, 3 - 2. Conclusion of Course X2 is a directory name and not file name.

How can I do that?

Update 1:

I could get the paths using:

for dir in $(find . -name '_QWE' -type d)/*/ ; do echo $dir ; done

or,

for dir in $(find . -name '_QWE' -type d)/*/ ; do (cd "$dir"; pwd); done

But,

for dir in $(find . -name '_QWE' -type d)/*/*/ ; do rename 's!^./(d+ -)s(d+.)!$1!' $dir ; done

Not yielding any output.

Asked By: Ahmad Ismail

||

You could use the -path modifier to pick out directories immediately under the matching directories:

find . -depth -type d -path '*/_QWE/*/*' ! -path '*/_QWE/*/*/*' -exec rename 's!(/d+)s+-s+d+.s+([^/]*)$!$1 $2!' {} +

I have modified your RE slightly to anchor it to the filename component of the matched path. (For PCRE expressions as used here, s+ matches one or more whitespace characters; d+ matches one or more digits; [^/]* matches a run of zero or more characters except /.)

Using your example tree of directories, here is the corresponding output when using rename -n:

./folder_1/_QWE/Course 1/2 - 1. Basics of Course 1 renamed as ./folder_1/_QWE/Course 1/2 Basics of Course 1
./folder_1/_QWE/Course 1/3 - 2. Conclusion of Course 1 renamed as ./folder_1/_QWE/Course 1/3 Conclusion of Course 1
./folder_1/_QWE/Course 2/2 - 1. Basics of Course 1 renamed as ./folder_1/_QWE/Course 2/2 Basics of Course 1
./folder_1/_QWE/Course 2/3 - 2. Conclusion of Course 1 renamed as ./folder_1/_QWE/Course 2/3 Conclusion of Course 1
./folder_2/folder_3/_QWE/Course X1/2 - 1. Basics of Course 1 renamed as ./folder_2/folder_3/_QWE/Course X1/2 Basics of Course 1
./folder_2/folder_3/_QWE/Course X1/3 - 2. Conclusion of Course 1 renamed as ./folder_2/folder_3/_QWE/Course X1/3 Conclusion of Course 1
./folder_2/folder_3/_QWE/Course X2/2 - 1. Basics of Course 1 renamed as ./folder_2/folder_3/_QWE/Course X2/2 Basics of Course 1
./folder_2/folder_3/_QWE/Course X2/3 - 2. Conclusion of Course 1 renamed as ./folder_2/folder_3/_QWE/Course X2/3 Conclusion of Course 1

For testing, I also added a sample set of directories using the same names under a folder_4 but not under a directory _QWE. As expected these were correctly ignored.

Answered By: roaima
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.