9

I want to rename a bunch of files using bash, transforming this file pattern:

prefix - name - suffix.txt 

Into this one:

name.txt 

For that I wrote the following script:

find . -name "*.txt" | while read f do mv "${f}" "${f/prefix - /}" done find . -name "*.txt" | while read f do mv "${f}" "${f/ - suffix/}" done 

It works, but I'd like to perform the renaming using a single loop. Is it possible?

4
  • 2
    If you have rename installed, try this: stackoverflow.com/questions/11990893/… Commented Aug 20, 2012 at 2:02
  • I'm in a Mac, I don't have rename installed by default Commented Aug 20, 2012 at 3:02
  • I'm using OSX and I have rename avaliable to me. Are you sure it isn't there? Commented Jan 14, 2014 at 19:54
  • @beth yep, still not available in my OSX. It must have been added on a later version (I'm using 10.8.5), or perhaps you installed it at some point. Commented Jan 15, 2014 at 3:08

4 Answers 4

10

Another approach, for fun, using regular expressions:

regex='prefix - (.*) - suffix.txt' for f in *.txt; do [[ $f =~ $regex ]] && mv "$f" "${BASH_REMATCH[1]}.txt" done 

Actually, using the simple pattern '*.txt' here has two problems:

  1. It's too broad; you may need to apply the regex to a lot of non-matching files.
  2. If there are a lot of files in the current directory, the command line could overflow.

Using find complicates the procedure, but is more correct:

find . -maxdepth 1 -regex 'prefix - .* - suffix.txt' -print0 | \ while read -d '' -r; do [[ $REPLY =~ $regex ]] && mv "$REPLY" "${BASH_REMATCH[1]}.txt" done 
Sign up to request clarification or add additional context in comments.

1 Comment

I like this answer. Just a comment: for the last part to work, it must be written as "${BASH_REMATCH[1]}.txt". Please fix it and I'll accept this answer
4

If you have access to GNU sed, you could use some regex to perform something like:

for i in *.txt; do mv "$i" "$(echo $i | sed -r 's/([^-]*)\s-\s(.*)\s-\s([^-]*)\.txt/\2.txt/')"; done 

Comments

1

you could use this:

find . -name "*.txt" -print0 | awk -v RS="\0" -v ORS="\0" '{print $0;sub(/^prefix - /,""); sub(/ - suffix.txt$/,".txt"); print $0; }' | xargs -0 -n 2 mv 

which could be written more clearly as:

find . -name "*.txt" -print0 | awk -v RS="\0" -v ORS="\0" '{ print $0; sub(/^prefix - /,""); sub(/ - suffix.txt$/,".txt"); print $0; }' | xargs -0 -n 2 mv 

Comments

1

If you have emacs installed. You can use the dired feature.

In bash:

# open your dir with emacs emacs /path/to/your/dir 

In emacs:

  • Press *%Enter\.txt$Enter to mark all txt files.
  • Press %rEnter.*- \(.*\) -.*Enter\1.txtEnter to rename.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.