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











