Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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?

share|improve this question
up vote 12 down vote accepted

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.

share|improve this answer
Nice - the most concise way so far. – Nathan Long Mar 2 '11 at 14:50

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
share|improve this answer
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
@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
@Matt Jenkins: FILES=`ls *.sql` <-- there. Shell expansion is built-in, no need for this extra ls. – Lekensteyn Mar 2 '11 at 14:56
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'
share|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}`
share|improve this answer

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .