How-To: Replace characters in filenames in Linux

Occassionally you’re likely to end up with a bunch of files with filenames that are underscore separated or space separated when you want them the other way around, and then you either have to manually rename them by hand, or live with it.

I had this issue the other day so I wrote a script to convert all filenames in the current directory to the specified format.

The script switches are:

  • -t – turns on [T]esting mode, which displays what would happen if you ran the script, but makes absolutely no changes to filenames.
  • -u – converts all [U]nderscores to spaces.
  • -s – converts all [S]paces to underscores.
  • -l – converts all filenames to [L]owercase.
  • -p – converts all filenames to u[P]percase.

It’d be nice if I could get all working recusively and offer an option to Capitalise Each Word in the filenames, but this will do for now.


  1. # Script to replace characters in filenames | September 2011 | r3dux
  2. # Note: This script will work on files in the present working directory only.
  3.  
  4. # Initiate counters
  5. changeCount=0;
  6. ignoreCount=0;
  7.  
  8. # Initiate flags
  9. displayUsage="FALSE"
  10. testRun="FALSE"
  11. u2sMode="FALSE"
  12. s2uMode="FALSE"
  13. toLowercase="FALSE"
  14. toUppercase="FALSE"
  15. proceed="FALSE"
  16.  
  17. # Set flags from the user provided parameters
  18. while getopts "htuslp" optname
  19. do
  20. 	case "$optname" in
  21. 		"h")
  22. 			displayUsage="TRUE"
  23. 			;;
  24. 		"t")
  25. 			echo "Test mode only - no filenames will be modified..."
  26. 			testRun="TRUE"
  27. 			;;
  28. 		"u")
  29. 			echo "Mode set to convert underscores to spaces..."
  30. 			u2sMode="TRUE"
  31. 			proceed="TRUE"
  32. 		        ;;
  33. 	        "s")
  34. 			echo "Mode set to convert spaces to underscores..."
  35. 			s2uMode="TRUE"
  36. 			proceed="TRUE"
  37. 		        ;;
  38. 		"l")
  39. 			echo "Mode set to convert filenames to lowercase..."
  40. 			toLowercase="TRUE"
  41. 			;;
  42. 		"p")
  43. 			echo "Mode set to convert filenames to uppercase..."
  44. 			toUppercase="TRUE"
  45. 			;;
  46. 		# Catch-all for unknown switches
  47. 	        *)
  48. 			echo
  49. 			echo "Unknown error while processing parameters. Please use -h to display usage paramaters."
  50. 			echo
  51. 			exit 0
  52.         		;;
  53. 	esac
  54. done
  55. echo
  56.  
  57. # If asked to, or if we got a parameter we don't recognise show the usage options
  58. if [ $displayUsage == "TRUE" ]; then
  59. 	echo "repchars is a small script to replace characters in filenames, or vice versa."
  60. 	echo
  61. 	echo "Usage: repchars [-t] (-u | -s) [-l | -p]"
  62. 	echo
  63. 	echo -e "-t\tturns on [T]esting mode, which displays what would happen if you ran the script, but makes absolutely no changes to filenames."
  64. 	echo -e "-u\tconverts all [U]nderscores to spaces."
  65. 	echo -e "-s\tconverts all [S]paces to underscores."
  66. 	echo -e "-l\tconverts all filenames to [L]owercase."
  67. 	echo -e "-p\tconverts all filenames to u[P]percase."
  68. 	echo
  69. 	echo "You can use use any combination of parameters except the mutually exclusive options -u and -s, and -l and -p."
  70. 	echo
  71. 	echo "It's recommended that you do a trial run with the -t switch to be sure the outcome is as you want it before commiting!"
  72. 	echo
  73.  
  74. 	exit 0;
  75. fi
  76.  
  77. # Moan if we have both 'toLowercase' and 'toUppercase' set (mutually exclusive)
  78. if [ $toUppercase == "TRUE" -a $toLowercase == "TRUE" ]; then
  79. 	echo "You cannot convert to both uppercase and lowercase at the same time."
  80. 	proceed="FALSE"
  81. fi
  82.  
  83. # Moan if we have both 'spaces-to-underscores' and 'underscores-to-spaces' set (mutually exclusive)
  84. if [ $s2uMode == "TRUE" -a $u2sMode == "TRUE" ]; then
  85. 	echo "You cannot convert spaces to underscores and underscores to spaces at the same time."
  86. 	proceed="FALSE"
  87. fi
  88.  
  89. # If the proceed flag isn't set, we don't proceed...
  90. if [ $proceed == "FALSE" ]; then
  91. 	echo "Please use repchars -h for usage instructions."
  92. 	echo
  93. 	exit 0;
  94. fi
  95.  
  96. # Function to replace characters dependent on the flags set
  97. function replaceChars()
  98. {
  99. 	# Note: Once we're in this function $1 isn't the first parameter passed to the 
  100. 	# script, it's the first (and only) parameter passed to this function.
  101.  
  102. 	# If appropriate, convert underscores to spaces
  103. 	if [ $u2sMode == "TRUE" ]; then
  104. 		newFilename=$(echo "$1" | tr _ ' ')
  105. 	fi
  106.  
  107. 	# If appropriate, convert spaces to underscores
  108. 	if [ $s2uMode == "TRUE" ]; then
  109. 		newFilename=$(echo "$1" | tr ' ' _)
  110. 	fi
  111.  
  112. 	# If apppropriate, convert filenames to lowercase
  113. 	if [ $toLowercase == "TRUE" ]; then
  114. 		newFilename=$(echo "$newFilename" | tr 'A-Z' 'a-z')
  115. 	fi
  116.  
  117. 	# If apppropriate, convert filenames to uppercase
  118. 	if [ $toUppercase == "TRUE" ]; then
  119. 		newFilename=$(echo "$newFilename" | tr 'a-z' 'A-Z')
  120. 	fi
  121.  
  122. 	# Only modify the filename if the original and new filenames are not the same thing
  123. 	# (i.e. there may be nothing to change, and if we mv the file to itself mv will complain)
  124. 	if [ "$1" != "$newFilename" ]; then
  125.  
  126. 		let changeCount+=1
  127.  
  128. 		if [ $testRun == "FALSE" ]; then
  129. 			echo "Original filename: $1"
  130. 			echo "New filename     : $newFilename"
  131. 			echo `mv "$1" "$newFilename"` # This actually renames the file
  132. 		else
  133. 			echo "*TESTRUN* Original filename: $1"
  134. 			echo "*TESTRUN* New filename     : $newFilename"
  135. 			echo
  136. 		fi
  137. 	else
  138. 		let ignoreCount+=1
  139.  
  140. 		echo -e "No change required to filename: $1"
  141. 	fi
  142. }
  143.  
  144. # Call the replacement function on each file
  145. for f in *; do
  146.  
  147. 	replaceChars "$f" 
  148.  
  149. done # End of file checking loop
  150.  
  151. # Finally, display the counts of filename changes and exit
  152. echo
  153. if [ $testRun == "TRUE" ]; then
  154. 	echo "We would have changed the filenames of $changeCount file(s) and ignored $ignoreCount file(s) which required no changing."
  155. else
  156. 	echo "Changed the filenames of $changeCount file(s) and ignored $ignoreCount file(s) which required no changing."
  157. fi
  158. echo

Like most scripting, this entire thing could probably be done in a single line, but I found it useful to learn how to use getopts and such.

Hope someone else finds it useful! Oh, and if you need a do-everything file renaming script, I read that FixNames script does what it says on the tin.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.