0

I'm looking to take a file name with spaces and replace the spaces with escape characters (i.e. "\ ") to use for file checking and manipulation. I'm using Bourne Shell (not bash) and I cannot use the sed command for implementation and portability reasons. I tried using parameter expansion, but I couldn't get it to work and I know that it is much less robust than in bash.

Example:

ITEM="file with spaces"            # What I have

WRAPPED_ITEM="file\ with\ spaces"  # What I need

PATTERN="\ "                       # What I tried
WRAPPED_ITEM="${ITEM/ /$PATTERN}"

Are there any workarounds for this?

5
  • If sed is unavailable, what can you use? The Bourne shell does not have sensible built-in features for this, though I suppose you could painstakingly do something with simple parameter expansions. Are you looking for a solution specifically for escaping spaces, or generally backslash a given set of characters, or even more generally substitute strings with other strings? Commented Mar 9, 2021 at 14:52
  • I'm just looking to escape spaces in this case. In some use cases sed may be available, but at least for the current implementation that I am developing this tool for, it is not. I am basing development on the GNU Coreutils list of commands found here. gnu.org/software/coreutils/manual/html_node/index.html Commented Mar 9, 2021 at 15:14
  • 1
    That's an odd choice; if you want a minimal base system, GNU Coreutils is a nontrivial amount of code. But anyway, Coreutils printf has the %q format specifier which does roughly what you seem to be asking. Commented Mar 9, 2021 at 15:26
  • It is an odd choice and, as it turns out, a poor one as well. I did some digging after reading your comment and you're right, the GNU Coreutils are not all available. Sadly, printf is one of the commands that is not available (as well as cut) so I think I will have to use some parameter expansion workaround. Commented Mar 9, 2021 at 16:02
  • Probably better if you can actually name your environment. Alpine Linux? Busybox? Weird for cut in particular to be missing; it can't be many bytes of code. Commented Mar 9, 2021 at 16:35

1 Answer 1

3

This can be done using portable variants of parameter expansions as shown below. The same algorithm should work for any character/character string on any modern POSIX shell.

quotews() {
  tmp=$1 out=
  while true; do
    case $tmp in
    *\ *) out="$out${tmp%% *}\\ "
          tmp=${tmp#* } ;;
       *) break
    esac
  done
  printf '%s\n' "$out$tmp"
}
$ quotews 'file with spaces'
file\ with\ spaces
Sign up to request clarification or add additional context in comments.

1 Comment

This is great. Thank you for your help. I had done something very similar using a while loop and some other local variables, but the case statement cleans it up very nicely and makes it a lot easier to read.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.