Dealing with filenames with spaces or quotes in bash
We've all been there — you've just written a beautiful bash script that takes in a list of files and fiddles with them beautifully.
It works perfectly…right up until the moment some nimrod introduces a file with spaces or quotes in it! Suddenly the script, at best, sputters to a halt or, at worst, starts creating a slew of fake files or replacing existing ones.
Sure, for certain commands you can use a null delimiter, using flags like --null or -print0 or -0 (would be kind of nice if this were standardized!). But not all commands do this. And even if all the commands you are using do support null one way or another, what a pain in the neck it is to go through all the different commands and fix them!
Turns out there's an easier solution — just fiddle with the filenames until they are correctly escaped!
In other words, turning this horrible and unsafe filename:
Final Document "Use This".docx
To this horrible but safe filename:
Final\ Document\ \"Use\ This\".docx
If you're doing a one liner, just pip it to this set of commands:
<command>|sed -E -e 's/ /\\ /g'|sed -E -e 's/([^\\])"/\1\\"/g'
The first sed escapes all spaces, the second one escapes all quotes UNLESS they've already been escaped (it happens). By the way, this means that if you have a filename that actualy has a backslash preceding a quote, then you're kind of screwed. Sorry!
If you're fiddling with variables or would like to put this in a centralized location in a bash script, here's a function:
function escape_filename() { echo "${1}"|sed -E -e 's/ /\\ /g'|sed -E -e 's/([^\\])"/\1\\"/g' }
Note the use of "${1}". It preserves whatever line breaks existed in the original filename listing.
Hope you find this useful!










