------------------------------------------------------------------------ Move *.cat to *.rat (in general from "inext" to "outext" ------------------------------------------------------------------------ Problem: In a sub-directory you have files with extension of cat. You wish to rename them with extension of of rat. #first we create the files we need $ touch Kitty{1..4}.cat $ ls -1 *.cat #the option is -1 (one) so we can a column list Kitty1.cat Kitty2.cat Kitty3.cat Kitty4.cat #we wish to rename "cat" to "rat". Note that the extension #is the characters after the last "." This is a rich problem with several solutions. A veritable fun fest for a geek. ------------------------------------------------------------------------ a pure "bash" solution ------------------------------------------------------------------------ $ cat moveit #!/bin/bash #usage: moveit extension new_extension #e.g. ./moveit rat cat (will result *.rat -> *.cat) # #note if extension has space then positional variables should be " " # ./moveit "hello rat" "hello cat" for file in *.$1 do file=${file%.*} #strip the characters after the last "." mv $file.$1 $file.$2 echo "mv $file.$1 $file.$2" #purely diagnostic (delete for usage) done $ chmod a+ moveit $ ./moveit cat rat ------------------------------------------------------------------------ solution using sed ------------------------------------------------------------------------ Let us start assuming that we want to a specifc move, *.cat -> *.rat $ ls -1 *.cat | sed 's/^\(.*\)\.\(.*\)$/mv \1.\2 \1.rat/' # <-- 1--> i<-- 2a 2b --> 1. ls: list files in a single column (default when not to screen) 2 pipe to sed: 2a: capture principal_file_name into token \1 and extension into token \2 2b:append "mv ". replace principal_file_name.extension by command mv \1.\2 \1.rat The output is mv Kitty1.cat Kitty1.rat mv Kitty2.cat Kitty2.rat mv Kitty3.cat Kitty3.rat mv Kitty4.cat Kitty4.rat Now we have to pass these commands to the shell so it can be executed $ ls -1 *.cat | sed 's/^\(.*\)\.\(.*\)$/mv \1.\2 \1.rat/' | sh -x # sh: pass each line to shell as a command to be executed. option "-x" traces execution (diagnostic; useful) ------------------------------------------------------------------------ A general version: variable input & output version ------------------------------------------------------------------------ Say you have such a "rename" need repeatedly and in some cases the input extension may "bat" and the desired output could be "ant" $ inext="rat" outext="bat" #note: no space surounding "=" $ echo $inext $outext #for invocation you need "$" prefix bat ant $ ls -1 *.$inext | sed "s/^\(.*\)\.\(.*\)$/mv & \1.${outext}/" | sh -x Incidentally you do not need the "-1" option. $ ls *.$inext | sed "s/^\(.*\)\.\(.*\)$/mv & \1.${outext}/" | sh -x I do not know whether this is a "feature" or bug (but saves 3 chars!) ------------------------------------------------------------------------ Convert to an executable (if frequently used) ------------------------------------------------------------------------ $ cat rename_extension #!/bin/bash inext=$1 outext=$2 ls *.$inext | sed "s/^\(.*\)\.\(.*\)$/mv & \1.${outext}/" | sh -x cntrl D $ chmod a+x rename_extension $ ./rename rat bat #Of course if you wish to have a shorter script (tempting) #you can directly invoke the positional parameters $ cat rename_extension #!/bin/bash ls *.$1 | sed "s/^\(.*\)\.\(.*\)$/mv & \1.$2/" | sh -x #note the switcht to double quotes from single quotes #double quotes allow for variable expansion ------------------------------------------------------------------------ sophisticated solution (allows for regular expressions, not merely strings ------------------------------------------------------------------------ $ cat rename4esp #!/bin/bash #Usage $ rename4esp ext "RegExp" "Replacement_String" #will rename the names of all files extension "ext" by #substituting "RegExp" by "ReplacementString". #Note that "RegExp" is actually a real regular expression #Of course it can accommodate a simple character sequence #composed by SRK for ESP # Example # $ rename4esp dat " " "_" # will rename files with extension "dat" # by substituting ALL blanks with underscores ls -1 *."$1" | awk '{a=$0;gsub(/'"$2"'/,'\""$3\""');print "mv","\""a"\"","\""$0"\""}' | sh -x