I've got some files like this:


...etc. I want to rename them to add AM, like this:


What's the most concise way to do that from the bash shell?


Another option:

for i in *.sql ; do
    mv -v $i ${i%.sql}-AM.sql

This loops through all the .sql files and renames them to end in -AM.sql instead.

PROTIP: Use $(command) instead of `command` in your scripts (and command-lines), it makes quoting and escaping less of a nightmare.

| improve this answer | |
  • Nice - the most concise way so far. – Nathan Long Mar 2 '11 at 14:50
  • The suggested edit is not an "attempt" to reply, but rather an extension of the original answer. It adds an explanation to the answer and not a reply. – zx485 Jul 2 at 2:14

Try this little script:


FILES=`ls *.sql`
for FILE in ${FILES}
    BASE=`basename ${FILE} .sql`
    mv ${FILE} ${BASE}-AM.sql

I just typed that from memory so if it doesn't work 100% don't blame me (i.e., back up your data first ;) )

How it works:

Collect all files into a variable (you could put this inside the for instead but I like to keep things easy to read):

FILES=`ls *.sql`

Loop through each file:

for FILE in ${FILES} { ... }

Get the filename without .sql:

BASE=`basename ${FILE} .sql`

Rename the file, adding -AM.sql to the base name:

mv ${FILE} ${BASE}-AM.sql
| improve this answer | |
  • 2
    You can remove the line FILES=`ls *.sql` and replace ${FILES} by *.sql, shell expansion will take care of finding the files. – Lekensteyn Mar 2 '11 at 14:48
  • This isn't the most concise way, but I do appreciate the readability and explanation. If I'm going to do this from the command line, I'd rather type what chrish shows, but if I were saving it as a script, I'd definitely use your way for readability. – Nathan Long Mar 2 '11 at 14:51
  • 1
    @Matt Jenkins: the readability does not increase by adding another ls command. Keep it simple. By the way, I think the { are bashish, it's better to replace them by do and done: for ...; do ...; done – Lekensteyn Mar 2 '11 at 14:53
  • 1
    @Matt Jenkins: FILES=`ls *.sql` <-- there. Shell expansion is built-in, no need for this extra ls. – Lekensteyn Mar 2 '11 at 14:56
  • 2
    Well forgive me for writing portable code. ls.. is just one source of files that the script could handle; it would be trivial to change it to use, say, a predefined list of files, or command line arguements, by just editing this variable. No need to change the structure of the for if you want to put the script to another use. Isn't that the point of this site? To give answers that are of interest to the genral populace? If that means making your scripts a little more wordy and a little more understandable then I don't see a problem with ls.. as it implicitly shows what is being worked on. – Majenko Mar 2 '11 at 15:01

Using the Perl script version of rename:

rename 's/\.sql$/-AM$&/' *.sql

Using the util-linux-ng version of rename (but only if ".sql" only appears at the end of the filename):

rename .sql -AM.sql *.sql

Using mmv:

mmv '*.sql' '#1-AM.sql'
| improve this answer | |

Since a Perl script has been suggested, here's a Ruby script to do the same:

`ls *.sql`.split("\n").each do |filename|
  new_filename = filename.split('.').join('-AM.')
  `mv #{filename} #{new_filename}`
| improve this answer | |

I suggest to use qmv from renameutils

The qmv program will open list of filenames of choosen directory in your default text editor and allows you to edit them. When you save this edited file list, it applies new names to actual files.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.