LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Bash script - escaping whitespaces (https://www.linuxquestions.org/questions/linux-newbie-8/bash-script-escaping-whitespaces-437968/)

colabus 04-23-2006 07:52 AM

Bash script - escaping whitespaces
 
Hi all,

I wrote a little script I'm using to do checksums on my backups.

Code:

typhon:/var/www# cat /var/www/md5chk.sh
#!/bin/bash

checksumDir="/home/www-data/checksums/"

if [ $# -lt 3 ] ; then
        echo "* Error: $0 [directory] [type] [number]"

        exit 1
else
        if [ -d $1 ] ; then
                for i in $( find $1 -type f ); do
                        md5sum -b $i >> $checksumDir/$2.$3
                done
        else
                echo "* Error: $1 is not a directory"

                exit 1
        fi
fi

echo "Successfully completed."

exit 0

My problem is with filename with whitespace characters in them. I can't quite work out how to make $i escape it's whitespace chars.

I'd imagine it's gonna something along the lines of: sed 's/ /\\ /' cause I can get it working with `echo "hello world" | sed 's/ /\\ /'`, I'm not sure how to apply this with the $i variable.

Could someone help me out with this? I've been googling for a while with no luck lol.

Cheers.

homey 04-23-2006 08:26 AM

Quote:

md5sum -b $i ....
Put the $i in quotes "$i"

colabus 04-23-2006 09:41 AM

Quote:

Originally Posted by homey
Put the $i in quotes "$i"

I have already tried that. Still get errors, I need the whitespaces escaped.

colabus 04-23-2006 10:02 AM

OK kinda got a little further here.

Code:

for i in $( find $1 -type f | sed 's/ /\\ /g' ); do
This does want I want but the problem is the the whitespace char, so "Hello\ World" will be 1. "Hello\" and 2. "World" in the loop. Any way in bash to make the for loop make i read the entire line?

Yes, I've tried quotes here too. Same problem.

Cheers

ioerror 04-23-2006 12:31 PM

My usual recommendation is to use zsh, which doesn't do stupid things like automatic word splitting on scalar variables. Bash is a poor excuse for a shell, IMO.

unSpawn 04-24-2006 06:21 PM

@colabus: the solution was handed to you by homey. The problem was obscured by the "for loop" expansion. Note that you best use "while loops" if you can't guesstimate what the expansion will amount to:
Code:

find $1 -type f|while read i; do md5sum -b "$i" >> $checksumDir/$2.$3; done

@ioerror:
Quote:

My usual recommendation is to use zsh
That's why all the OSes install Zsh as default shell and all the "important" apps are written as or ported to zsh shell scripts, right?.. Not.

ioerror 04-24-2006 06:33 PM

Quote:

That's why all the OSes install Zsh as default shell
Er, zsh is the default shell on MacOS X. NetBSD has it's own shell, other "OSes" use other shells, etc. Bash is the default shell on Linux because bash is the GNU shell, and Linux systems are GNU systems. So what? Any complete distribution will include zsh, tcsh, ksh etc. A distro that only installs bash is one I wouldn't touch with barge pole.

Quote:

the "important" apps are written as or ported to zsh shell scripts, right?
I thought that "important" apps were written in C.

There is nothing magical about bash, it is just the GNU shell. I don't think it's very good, it has lots of stupidities, like automatic word splitting. So I use zsh, and I merely suggested that the querent give it a try since it will automatically solve his problem. What's wrong with that?

unSpawn 04-24-2006 08:35 PM

I thought that "important" apps were written in C.
Yeah, I should probably rephrase that as: "there are more popular and commonly used tools written in Bash compared to Zsh".


like automatic word splitting.
See IFS variable.


I merely suggested that the querent give it a try since it will automatically solve his problem. What's wrong with that?
I'm not questioning your competence but, considering the "fix" is that trivial, substituting Bash for zsh is utterly unnecessary.

timmeke 04-25-2006 06:27 AM

@colabus:
to summarize the discussion between ioerror and unSpawn:
set $IFS prior to your for-loop.
Give it a value like "\n" (newline) only.
This should make the for-loop avoid splitting the words (shell splits up the words on spaces, tabs and newlines by default) that come out of the "find" command.

See:
Code:

man bash
and search for "IFS".

T.Hsu 04-25-2006 07:06 AM

Why not use find's `-exec' command?

timmeke 04-25-2006 07:14 AM

Good point, H. Tsu.

An alternative would be to use the -print0 option of "find" and to pipe it into xargs -0.
I've seen solutions like that around on this forum too.

T.Hsu 04-25-2006 07:18 AM

Or

for i in "$(find . -maxdepth 1 -type f)"; do md5sum "$i"; done

T.Hsu 04-25-2006 07:48 AM

Also

find . -type f | while read line; do md5sum "$line"; done

Note newline char is "legal" in filename, so this one may not work properly.

The best solution I think is

find . -type f -print0 | xargs --null md5sum

ioerror 04-25-2006 10:50 AM

Quote:

there are more popular and commonly used tools written in Bash compared to Zsh
Well, bash is more prevalent (at least on Linux), so it's natural that more people would use it, but zsh could probably run most of those scripts without modification, although it does have a few subtle incompatibilities with POSIX syntax.

Quote:

I'm not questioning your competence but, considering the "fix" is that trivial, substituting Bash for zsh is utterly unnecessary.
OK, for a single case I would agree, but personally I haven't used bash for years, so no substitution occurs! ;)

I don't want to start a pointless bash vs. zsh debate but zsh has lots of other features (e.g. nested parameter expansion (which bash still can't do), associative arrays, etc) which makes it an excellent choice both for scripting and interactive use. OK, I'm going to stop now. I only mentioned it in the first place because bash is so prevalent and the lesser known shells often get overlooked. After all, Linux is all about choice...

unSpawn 04-25-2006 11:03 AM

I don't want to start a pointless bash vs. zsh debate
Me neither.


but zsh has lots of other features (e.g. nested parameter expansion (which bash still can't do), associative arrays, etc)
Yes, you're right there. Bash' array-fu certainly isn't that evolved.


All times are GMT -5. The time now is 05:31 AM.