How to pass directory with escaped space to variable?

10,433

Solution 1

You could try like this:

Example 1: Your answer.

#!/bin/bash
read -e -p "Enter a Directory: " directory
new_directory="$(echo $directory | sed 's/ /\\ /g')"
echo $new_directory

Example 2: If you are going to cd script output wrap it with double quote.

#!/bin/bash
read -e -p "Enter a Directory: " directory
new_directory=\"$directory\"
echo $new_directory

Solution 2

There is no escaped space in the variable to keep. When you enter ~/A Directory/ at the prompt, the variable directory contains ~/A Directory/. If you're having trouble with this space later in your script, it's because you forgot the double quotes around variable expansions.

read -e -p "Enter a Directory: " directory
ls -- "$directory"
cd -- "$directory"

The -- is in case the value starts with -, so that it isn't treated as an option.

If for some reason you want to add a backslash before spaces, you can do it with bash's string manipulation features.

echo "${directory// /\\ }"

This is highly unlikely to be useful though. If you need to print out the directory in a form that will be parsed again, there will definitely be other characters to quote. Which characters depends on what's going to parse it, but at the very least tabs (and newlines, but your script is unable to read them) will need quoting if spaces do, and a backslash will also need to be quoted. Bash doesn't have a convenient way to do that. You can use sed, but be careful when passing the data to it — echo does not print all arguments unmodified. An added difficulty command substitution strips trailing newlines, but you won't have newlines here.

quoted_directory=$(printf %s "$directory" | sed 's/[\\ '$'\t'']/\\&/')

Note also that nothing here expands the tilde at the beginning. (The output you show is faked, naughty you!) Tilde expansion only happens as part of source code parsing, it does not happen when the value of a variable is expanded. If you want to replace an initial tilde with the home directory, you'll need to do it manually.

read -e -p "Enter a Directory: " directory
if [[ $directory = \~/* ]]; then
  directory="$HOME/${directory#*/}"
fi
ls -- "$directory"
cd -- "$directory"

Solution 3

Per https://askubuntu.com/a/344418,

Clear the IFS variable thusly:

   IFS=$'\n'       # make newlines the only separator

Then continue your script.

Share:
10,433

Related videos on Youtube

Admin
Author by

Admin

Updated on September 18, 2022

Comments

  • Admin
    Admin almost 2 years

    I have a small test.sh script as follows:

    #!/bin/bash
    read -e -p "Enter a Directory: " directory
    echo $directory
    

    Here's what happens when I run it:

    $ ./test.sh 
    Enter a Directory: ~/A\ Directory/
    /Users/<username>/A Directory/
    

    I want to be able to keep the escaped space inside that variable so that the program output would read:

    $ ./test.sh 
    Enter a Directory: ~/A\ Directory/
    /Users/<username>/A\ Directory/
    

    Anyone know how to do this? The use for this is to tell the script where to look for files that it needs to read.

    Edit: I forgot to put the \ in the second and third code selection.

    • Admin
      Admin over 8 years
      @snoop I am going to read files from that directory from another directory.
  • Admin
    Admin over 8 years
    Both answers seem to work for me. Thank you for your help.
  • Admin
    Admin over 8 years
    Please see my edit above. I want to be able to enter a directory in the form of ~/A\ Directory/ and be able to use that directory normally without the space causing a break in cd or ls commands. In my particular case I am telling the script where it will look for files to read.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 8 years
    @MatthewSanabria I'm confused now: do you want to remove the backslash that you typed? Keep in mind that in your tests, you are not printing the value of the variable: you're splitting it, doing globbing on it, and then letting echo mangle it further. To print the exact value of a variable, use printf %s "$directory". If you want a newline after it, use printf '%s\n' "$directory". If you want to use what you typed unmodified, I've given snippets to do that in my answer.
  • Admin
    Admin over 8 years
    I want to be able to have the script ask a user for a directory. The user should be able to use the tab key to auto complete the directory name. That would result in "~/A\ Directory" if the directory had a space in the name. I want to be able to keep that directory name in a variable that I can use to read files from and/or use cd and ls.
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 8 years
    @MatthewSanabria Actually, read performs backslash expansion on its input (because you didn't pass -r), so what you get in the variable is the right form to pass to cd except that completion allows an initial ~. There is no backslash in the value of the variable, and you must not have a backslash there to pass it to cd (unless the name of the directory contains a backslash of course). So my last snippet will work for you. Once again, keep in mind that echo $directory does NOT print the value of the variable directory; you need printf '%s\n' "$directory" for that.
  • Admin
    Admin over 8 years
    Thank you for the quick replies. I will try your snippets when I get home later and update the post.