Work the Shell - Dealing with Spaces in Filenames

 in
How do you deal with this problem in your scripts?

and reversed with:

original="$(echo $safename | sed s'/_-_/ /g')"

It solves the problem, but it's definitely not a very efficient or smart use of computing resources.

I've outlined three possible solution paths herein: modifying the IFS value, ensuring that you always quote filenames where referenced, and rewriting filenames internally to replace spaces with unlikely character sequences, reversing it on your way out of the script.

By the way, have you ever tried using the find|xargs pair with filenames that have spaces? It's sufficiently complicated that modern versions of these two commands have special arguments to denote that spaces might appear as part of the filenames: find -print and xargs -0 (and typically, they're not the same flags, but that's another story).

During the years I've been writing this column, I've more than once tripped up on this particular problem and received e-mail messages from readers sharing how a sample script tosses up its bits when a file with a space in its name appears. They're right.

My defensive reaction is “dude, don't use spaces in filenames”, but that's not really a good long-term solution, is it?

What I'd like to do instead is open this up for discussion on the Linux Journal discussion boards: how do you solve this problem within your scripts? Or, do you just religiously avoid using spaces in your filenames?

Dave Taylor has been hacking shell scripts for a really long time, 30 years. He's the author of the popular Wicked Cool Shell Scripts and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.

______________________

Dave Taylor has been hacking shell scripts for over thirty years. Really. He's the author of the popular "Wicked Cool Shell Scripts" and can be found on Twitter as @DaveTaylor and more generally at www.DaveTaylorOnline.com.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Why not using the IFS??

Saladin's picture

I've gone through this dilemma in recent project and found using IFS simple and very effective,

Is this possible for all cases and the one mentioned in the article above?

IFS_backup=$IFS

IFS=$(echo -en "\n\b")

#do what ever you want ... then restore the original variable

IFS=$IFSBU

--

Salah Aldeen

Regards,

The problem, internal shell conversions

xae's picture

To manage this problem I had been using code like this,


for filename in *; do aux=$filename/; LS[${#LS[@]}]=${aux%/}; done
...
rm "${LS[24]}", as example

The catch here is to avoid the conversions taken by the shell when you access to the content of a variable, the trick is to append to the variable a character, trying to make the shell guess that it's a string, and then you can gain access without infamous conversions, but at later you ougth to remove the char in order to use it as a filename.

The chars candidates for this job are NUll, $'/0, and "/".

s/find -print/find -print0/ ?

mattcen's picture

Dave, did you mean '-print0' as opposed to '-print'? While both kind of make sense, when paired with 'xargs -0' I think the former makes *more* sense.

With respect to spaces, I usually don't bother dealing with them unless I *know* that they'll be there (e.g. I'm manipulating data that non-geek customers access via a Samba share and put plenty of weird characters in).

One of the other solutions I've considered, but not really had to use yet, is to switch to Perl or Python for these particular use-cases, given they handle escaping of spaces somewhat better.

It's something I'd rather not do given I'm more familiar with Bash than either of the above, but it may be the lease bad solution, even if I do have to dig up my text books to work out how to do something that would be trivial in Bash.

--
Regards,
Matthew Cengia

White Paper
Linux Management with Red Hat Satellite: Measuring Business Impact and ROI

Linux has become a key foundation for supporting today's rapidly growing IT environments. Linux is being used to deploy business applications and databases, trading on its reputation as a low-cost operating environment. For many IT organizations, Linux is a mainstay for deploying Web servers and has evolved from handling basic file, print, and utility workloads to running mission-critical applications and databases, physically, virtually, and in the cloud. As Linux grows in importance in terms of value to the business, managing Linux environments to high standards of service quality — availability, security, and performance — becomes an essential requirement for business success.

Learn More

Sponsored by Red Hat

White Paper
Private PaaS for the Agile Enterprise

If you already use virtualized infrastructure, you are well on your way to leveraging the power of the cloud. Virtualization offers the promise of limitless resources, but how do you manage that scalability when your DevOps team doesn’t scale? In today’s hypercompetitive markets, fast results can make a difference between leading the pack vs. obsolescence. Organizations need more benefits from cloud computing than just raw resources. They need agility, flexibility, convenience, ROI, and control.

Stackato private Platform-as-a-Service technology from ActiveState extends your private cloud infrastructure by creating a private PaaS to provide on-demand availability, flexibility, control, and ultimately, faster time-to-market for your enterprise.

Learn More

Sponsored by ActiveState