简体   繁体   中英

Shell Script for Bulk renaming of files

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?

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

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.

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

在此处输入图片说明


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

人行

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM