Batch renaming files with Bash


You could use bash's parameter expansion feature

for i in ./*.pkg ; do mv "$i" "${i/-[0-9.]*.pkg/.pkg}" ; done

Quotes are needed for filenames with spaces.

If all files are in the same directory the sequence

ls | 
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' | 

will do your job. The sed command will create a sequence of mv commands, which you can then pipe into the shell. It's best to first run the pipeline without the trailing | sh so as to verify that the command does what you want.

To recurse through multiple directories use something like

find . -type f |
sed -n 's/\(.*\)\(-[0-9.]*\.pkg\)/mv "\1\2" "\1.pkg"/p' |

Note that in sed the regular expression grouping sequence is brackets preceded by a backslash, \( and \), rather than single brackets ( and ).

I'll do something like this:

for file in *.pkg ; do
    mv $file $(echo $file | rev | cut -f2- -d- | rev).pkg

supposed all your file are in the current directory. If not, try to use find as advised above by Javier.

EDIT: Also, this version don't use any bash-specific features, as others above, which leads you to more portability.