-2

I want to recursively rename all files in directory path by changing their prefix.

For Example

XYZMyFile.h
XYZMyFile.m
XYZMyFile1.h
XYZMyFile1.m
XYZMyFile2.h
XYZMyFile2.m

TO

ABCMyFile.h
ABCMyFile.m
ABCMyFile1.h
ABCMyFile1.m
ABCMyFile2.h
ABCMyFile2.m

These files are under a directory structure with many layers. Can someone help me with a shell script for this bulk task?

SaintHax
  • 1,875
  • 11
  • 16
Vikash
  • 213
  • 5
  • 15
  • 1
    Rename first 3 characters from `XYZ` to `ABC`, seems so trivial? What did you try? Did you look up similar answers before posting here? – Inian Jun 21 '17 at 11:56
  • use `rename` Perl function on command line. If you familiar with `C++` use my [renrem](https://github.com/k-five/renrem) program or use [drr](https://github.com/k-five/drr) which is on `D` language. – Shakiba Moshiri Jun 21 '17 at 11:58
  • edit suggestion queue is full :-) and it's easy enough that 4 various ways have been provided – SaintHax Jun 21 '17 at 17:40

4 Answers4

1

A different approach maybe:

ls *.{h,m} | while read a; do n=ABC$(echo $a | sed -e 's/^XYZ//'); mv $a $n; done

Description:

ls *.{h,m} --> Find all files with .h or .m extension
n=ABC --> Add a ABC prefix to the file name
sed -e 's/^XYZ//' --> Removes the XYZ prefix from the file name
mv $a $n --> Performs the rename
justaguy
  • 2,908
  • 4
  • 17
  • 36
  • ls: *.h: No such file or directory ls: *.m: No such file or directory. i got these two line as output – Vikash Jun 21 '17 at 15:19
  • did you `cd` to where the files are located? Where are the files located? – justaguy Jun 21 '17 at 23:38
  • 1
    You may want to add quotes for dealing with any filenames that have spaces in them. mv "$a" "$n"; – tgf Aug 07 '17 at 09:16
-1

Set globstar first and then use rename like below:

# shopt -s globstar # This will cause '**' to expand to each and everything
# ls -R
.:
nXYZ1.c  nXYZ2.c  nXYZ3.c  subdir  XYZ1.m  XYZ2.m  XYZ3.m
nXYZ1.h  nXYZ2.h  nXYZ3.h  XYZ1.c  XYZ2.c  XYZ3.c
nXYZ1.m  nXYZ2.m  nXYZ3.m  XYZ1.h  XYZ2.h  XYZ3.h

./subdir:
nXYZ1.c  nXYZ1.m  nXYZ2.h  nXYZ3.c  nXYZ3.m  XYZ1.h  XYZ2.c  XYZ2.m  XYZ3.h
nXYZ1.h  nXYZ2.c  nXYZ2.m  nXYZ3.h  XYZ1.c   XYZ1.m  XYZ2.h  XYZ3.c  XYZ3.m
# rename 's/^XYZ(.*.[mh])$/ABC$1/;s/^([^\/]*\/)XYZ(.*.[mh])$/$1ABC$2/' **
# ls -R
.:
ABC1.h  ABC2.m  nXYZ1.c  nXYZ2.c  nXYZ3.c  subdir  XYZ3.c
ABC1.m  ABC3.h  nXYZ1.h  nXYZ2.h  nXYZ3.h  XYZ1.c
ABC2.h  ABC3.m  nXYZ1.m  nXYZ2.m  nXYZ3.m  XYZ2.c

./subdir:
ABC1.h  ABC2.h  ABC3.h  nXYZ1.c  nXYZ1.m  nXYZ2.h  nXYZ3.c  nXYZ3.m  XYZ2.c
ABC1.m  ABC2.m  ABC3.m  nXYZ1.h  nXYZ2.c  nXYZ2.m  nXYZ3.h  XYZ1.c   XYZ3.c
# shopt -u globstar # Unset gobstar

This may be the simplest way to achieve your objective.


Note1 : Here I am not changing nXYZ to nABC as you have noticed. If they are meant to be changed the simplified rename command would be

rename 's/XYZ(.*.[mh])$/ABC$1/' **

Note2 : The question has mentioned nothing about multiple occurrences of XYZ. So nothing done in this regard.

sjsam
  • 21,411
  • 5
  • 55
  • 102
-1

For non-recursive, you can use rename which is a perl script:

rename -v -n 's/^.+(?=MyFile)/what-you-want/' *.{h,m}  

test:

 dir >  ls | cat -n
     1  XYZMyFile1.h
     2  XYZMyFile1.m
     3  XYZMyFile.h
     4  XYZMyFile.m
 dir >  
 dir >  rename -v -n 's/^.+(?=MyFile)/what-you-want/' *.{h,m}
rename(XYZMyFile1.h, what-you-wantMyFile1.h)
rename(XYZMyFile1.m, what-you-wantMyFile1.m)
rename(XYZMyFile.h, what-you-wantMyFile.h)
rename(XYZMyFile.m, what-you-wantMyFile.m)
 dir >  

and for recursive,use find + this command


If you do not have access to rename, you can use perl directly like so:

perl -le '($old=$_) && s/^xzy/abc/g && rename($old,$_) for <*.[mh]>'

and here is a screen-shot

enter image description here


and with renrem, a CLI I developed using C++, specifically for renaming

renrem

Shakiba Moshiri
  • 21,040
  • 2
  • 34
  • 44
  • after XYZ MYFILE is not same. it can be any filename. XYZMyFile1.h XYZnewFile.h, XYZOldFile.h. Only thing common is prefix. And I want to replace that. Your script seems to take MYFile into consideration, so can you modify your script. – Vikash Jun 21 '17 at 15:12
  • Yes, if you be more specific please. I developed three apps just on renaming files. It is so easy for me if you explain your pattern exactly. – Shakiba Moshiri Jun 21 '17 at 16:11
-1

Easy find and rename (the binary in /usr/bin, not the Perl function mentioned)

Yes, there is a command to do this non-recursive already.

rename XYZ ABC XYZ*

rename --help

Usage:
 rename [options] expression replacement file...

Options:
 -v, --verbose    explain what is being done
 -s, --symlink    act on symlink target

 -h, --help     display this help and exit
 -V, --version  output version information and exit

For more details see rename(1).

edit: missed the "many layers of directory" part of the question, b/c it's a little messy. Adding the find.

Easiest to remember:

find . -type f -name "*.pdf" -exec rename XYZ ABC {} \;

Probably faster to finish:

find . -type d -not -path "*/\.*" -not -name ".*" -exec rename XYZ ABC {}/*.pdf \;

I'm not sure how to get easier than one command line of code.

SaintHax
  • 1,875
  • 11
  • 16