How To: Simply Convert A Directory of FLAC files to MP3 with FFMPEG in Linux

Stick the following in a file called flac2mp3 or such, chmod +x it, then put it in somewhere like /usr/local/bin

for a in *.flac; do
  ffmpeg -i "$a" -qscale:a 0 "${a[@]/%flac/mp3}"
done

To use it, simply go to your folder of .flac files and run flac2mp3, then perhaps rm *.flac to get rid of the (massive) flac files you don’t want anymore.

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.

How to: Get absolute/relative file paths, filenames and extensions from a Bash script

I’ve been learning some Qt stuff today, and the resulting code requires pre-processing of header files to work correctly, which I thought I’d try to automate. As part of this, I needed to find out how to get at all the different elements of a file from a bash script, so I did some googling and got all the info I needed :)

The script itself isn’t particularly useful, but the component parts of how to get at paths, extensions, and plain filenames without extensions definitely is – check it out:

fileParts Shell Script

# Bash script to get filename details | 16-06-2011 | r3dux
# Usage: fileParts <extension-with-no-dot> i.e. fileParts cpp
 
# For each file with the given extension in the current directory...
for file in ./*.$1; do
 
	# If a file exists with a given extension...
	if [ -e "$file" ]; then
 
		fullPath=$(readlink -f "$file")
		echo "Full path and filename          is: " $fullPath
 
		echo "Relative path and filename      is: " $file
 
		fileWithoutPath=$(basename $file)
		echo "Filename only                   is: " $fileWithoutPath
 
		extension=${fileWithoutPath##*.}
		echo "File extension only             is: " $extension
 
		fileWithoutExtension=${fileWithoutPath%.*}
		echo "Filename only without extension is: " $fileWithoutExtension
 
		echo
	else
		echo "No files of type $1 found!"
		exit 0
 
	fi # End of if file exists condition				
 
done # End of for each file loop

I created two dummy “.h” files in my home folder and ran the script – this is what it outputs:

r3d2@r3dux-Aspire-8920:~$ ./fileParts h
Full path and filename          is:  /home/r3d2/a-simple-test-file.h
Relative path and filename      is:  ./a-simple-test-file.h
Filename only                   is:  a-simple-test-file.h
File extension only             is:  h
Filename only without extension is:  a-simple-test-file
 
Full path and filename          is:  /home/r3d2/file.with.lots.of.dots.h
Relative path and filename      is:  ./file.with.lots.of.dots.h
Filename only                   is:  file.with.lots.of.dots.h
File extension only             is:  h
Filename only without extension is:  file.with.lots.of.dots

That’s gotta come in useful, right? =D

How To: Remove all desktop.ini (or indeed any recurring) files in Linux

I spent a while going through my music hive today, just putting music I’d ripped and dumped into the New folder into the correct spot, placing all albums by the same band into a folder called the band name etc, and there’s a hella lot of desktop.ini and Thumbs.db files floating around. This might be useful for people running Windows, but I’m not (or at least not anymore, and not for a long, long time) – so lets be rid of them, shall we?

Blatantly Unnecessary Warning: Deleting files deletes files! Fo’ real, yo! So try out the “tester” script before unconditionally deleting things you might now want to! =D

Measure Twice, Cut Once

Before we delete files en masse – let’s check to see what files we’re opting to remove. To do this, and assuming we want to check what desktop.ini files we can remove, just enter something along the lines of the following into the bash:

find path-to-folder -name desktop.ini

For example, if my music is stored on my NAS at /mnt/Share/_Serva, then to check what files will be removed, I’ll enter:

find /mnt/Share/_Serva -name desktop.ini

After hitting return on the above, you should be given a list of instances of files called desktop.ini and we get to put our minds at ease that it’s not even thinking about adding any other files (such as mp3s or what-have-you) to the list.

Cease and Desist

Once we’re happy we’re going to remove only the files we want gone, to interactively delete all the desktop.ini files from a given folder and any subfolders (and by interactively, I mean it’ll ask you whether you want to delete each one), enter the following command into the bash:

find path-to-folder -name desktop.ini -exec rm -i {} \;

So in my instance, to interactively (i.e. I’d then have to confirm each delete) remove all instances of desktop.ini, I’d enter:

find /mnt/Share/_Serva -name desktop.ini -exec rm -i {} \;

If I wanted to automatically remove all copies of files named desktop.ini without confirming each deletion, then I can just strip off the -i switch, leaving:

find path-to-folder -name desktop.ini -exec rm {} \;

You can then do the same thing for Thumbs.db or any other filename just by substituting the appropriate details after the -name switch.

Done & done =D

P.S. Just for the record, removing the -i will make the deletion occur automatically unless the file is write-protected, but you can always sudo that away, just like the request for a sandwich.

Credits & thanks: MegaJim over on Ubuntu Forums.

How To: Convert a Directory of MP3s to WAVs in Linux

I went to burn a couple of audio CDs for the boy today, and bod-frickn-dammit if Brasero / GnomeBaker and K3B didn’t all threw their hands in the air in dismay that I might actually have the nerve to want to convert mp3s to CD-audio on the fly. Very poor.

So, as wav files come in less flavours than mp3s and tend to work first time, I knocked up a quick script to convert a directory of mp3s to .wav files using mpg123, it even handles spaces correctly after I’d given it a stern talking to… Anyways:

#/bin/bash
gotmpg123=$(which mpg123)
 
# If there's no copy of mpg123 we're not going to be doing any converting. Abort!
if [ "$gotmpg123" = "" ]; then
    echo "No copy of mpg123 found on system! Try running: sudo apt-get install mpg123"
    exit 0
fi
 
# Otherwise, if we're all set, make a directory to dump our wav files into
mkdir WAV
 
# For each file in the current directory that ends with .mp3, convert it to .wav and place in our new WAV folder
for file in ./*.mp3
do
  mpg123 -w ./WAV/"${file}".wav "$file"
done

To use the script:
– Copy and paste the above code into a new text file called mp32wav or something
– Make it executable with chmod +x mp32wav, then
– Copy it to /usr/local/bin for easy access with sudo cp mp32wav /usr/local/bin/

With that all done you can just go into a folder of mp3s in the terminal and fire it off. It’ll create a folder called WAV inside whatever directory you’re in and stick the converted wav files there with the original filename but with .wav tacked on the end.

Cheers!