Results 1 to 9 of 9

Thread: [BASH] tilde doesn't expand from user input?

  1. #1
    Join Date
    Mar 2012
    Location
    the Shire
    Beans
    225
    Distro
    Ubuntu 12.04 Precise Pangolin

    [BASH] tilde doesn't expand from user input?

    I am learning some bash scripting, and I want to have the user type in a path to some directory and allow the use of ~
    so that
    Code:
    echo 'type path to somedir'
    read -e -p "> " path
    path=${path//\~/$HOME}
    echo 'your path:'
    echo $path
    however, it seems the tilde charecter cannot be replaced??

    EDIT:
    fixed code, thanks.
    Last edited by gandalf3; May 22nd, 2013 at 12:56 AM. Reason: fix code
    Intel Pentium 4 Asus P5N32-SLI DELUXE Nvidia nx7900GT 3GB Ram Western Digital WD2500AAKX 250GB Seagate Barracuda 80GB, 160GB Ubuntu 12.04 Arch

  2. #2
    Join Date
    Feb 2013
    Beans
    Hidden!

    Re: [BASH] tilde doesn't expand from user input?

    Try
    Code:
    path=${path/#\~/$HOME}
    Actually, there's not much point in such substitution as you can force tilde expansion with eval: Edit. Too dangerous, see Vaphell's post below.
    Code:
    read -ep 'type path to somedir ' path
    eval echo your path: $path
    Moreover, tilde not always expands to $HOME. E.g. ~user means home directory of user, ~+ = $PWD, ~- = $OLDPWD, and so on.

    Note also that your code has other problems, too: no prompt after read -p and single quotes in the last line (shell parameters get expanded only inside double quotes).
    Last edited by schragge; March 25th, 2013 at 11:07 AM.

  3. #3
    Join Date
    Mar 2012
    Location
    the Shire
    Beans
    225
    Distro
    Ubuntu 12.04 Precise Pangolin

    Re: [BASH] tilde doesn't expand from user input?

    Try
    Code:

    path=${path/#\~/$HOME}
    oh wow that worked! thanks.
    thanks for the tip about eval, i think i'll use that.
    though i can't get the variable path reassigend to the eval-ifide path??

    Code:
    read -ep '> ' path
    path= eval echo $path
    echo $path
    EDIT


    i can't mark as solved in "thread tools"??

    im not used to the new interface yet.. probably just me being an idiot
    Last edited by gandalf3; March 24th, 2013 at 11:17 PM. Reason: no "mark as solved"
    Intel Pentium 4 Asus P5N32-SLI DELUXE Nvidia nx7900GT 3GB Ram Western Digital WD2500AAKX 250GB Seagate Barracuda 80GB, 160GB Ubuntu 12.04 Arch

  4. #4
    Join Date
    Feb 2013
    Beans
    Hidden!

    Re: [BASH] tilde doesn't expand from user input?

    Quote Originally Posted by gandalf3 View Post
    i can't mark as solved in "thread tools"??
    You need to edit the thread name manually as described in this post.
    Last edited by schragge; March 25th, 2013 at 03:49 AM. Reason: thanks Vaphell

  5. #5
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: [BASH] tilde doesn't expand from user input?

    for gods sake never eval user input.

    what if someone types
    Code:
    ; rm -rf ~
    ?

    stick to ${path/#\~/$HOME}
    if your question is answered, mark the thread as [SOLVED]. Thx.
    To post code or command output, use [code] tags.
    Check your bash script here // BashFAQ // BashPitfalls

  6. #6
    Join Date
    Feb 2013
    Beans
    Hidden!

    Re: [BASH] tilde doesn't expand from user input?

    You are right. Then maybe do it like this:
    Code:
    IFS=';&|()`'
    read -ep '> ' path junk
    path=$(eval echo $path)
    echo $path
    I see why this is suboptimal and rather fragile as it would break on paths containing characters listed in $IFS, but at least the full semantics of ~ would be preserved.

    Update.
    After giving it some more thought, now I guess the most prudent way would be using the case statement:
    Code:
    #!/bin/sh
    LC_ALL=C # for [a-z] to work as expected
    test -n "$1" && path=$1 || read -p '> ' path
    case $path in ~*)
     pfx=${path%%/*}; tag=${pfx#\~}; tail=${path#$pfx}
     case $tag in
      '')  path=$HOME$tail;;
      +) path=$PWD$tail;;
      -) test -n "$OLDPWD" && path=$OLDPWD$tail;;
      [a-z_]*) passwd=`getent passwd "$tag"` && pfx=${passwd%:*}&&path=${pfx##*:}$tail;;
    # Some custom shortcuts
      DC) path=$HOME/Documents$tail;;
      DL) path=$HOME/Downloads$tail;;
      DT) path=$HOME/Desktop$tail;;
      ML) path=$HOME/Mail$tail;;
      MU) path=$HOME/Music$tail;;
      PC) path=$HOME/Pictures$tail;;
      PB) path=$HOME/Public$tail;;
      TL) path=$HOME/Templates$tail;;
      VD) path=$HOME/Videos$tail;;
      CF) path=$HOME/.config$tail;;
      LC) path=$HOME/.local/share$tail;;
      MD) path=/media$tail;;
     esac
    esac
    echo $path
    The same in bash
    Code:
    #!/bin/bash
    LC_ALL=C # for [a-z] to work as expected
    shopt -s extglob # for $DIRSTACK
    declare -A shortcuts
    shortcuts=(
     [DC]=Documents [DL]=Downloads [DT]=Desktop [ML]=Mail [MU]=Music
     [PC]=Pictures [PB]=Public [TL]=Templates [VD]=Videos [CF]=.config
     [LC]=.local/share
    )
    [[ -n $1 ]] path=$1 || read -ep '> ' path
    if [[ $path == ~* ]]; then
     pfx=${path%%/*}; tag=${pfx:1}; tail=${path#$pfx}
     case $tag in
     '') path=$HOME$tail;;
     +) path=$PWD$tail;;
     -) [[ -n $OLDPWD ]] && path=$OLDPWD$tail;;
     ?(+|-)+([0-9])) path=${DIRSTACK[$tag]}$tail;;
     DC|DL|DT|MU|PC|PB|TL|VD|CF|LC) path=$HOME/${shortcuts[$tag]}$tail};;
     MD) path=/media$tail;;
     [a-z_]*) ifs=$IFS;IFS=:; passwd=(`getent passwd "$tag"`)&&path=${passwd[5]}$tail; IFS=$ifs;;
     esac
    fi
    echo $path
    Last edited by schragge; March 29th, 2013 at 02:46 PM.

  7. #7
    Join Date
    Mar 2012
    Location
    the Shire
    Beans
    225
    Distro
    Ubuntu 12.04 Precise Pangolin

    Re: [BASH] tilde doesn't expand from user input?

    That is a LOT of stuff... for something as seemingly simple as makeing "~" work in the read command..
    (i see the problem though.. there seems like there ought to be some way to eval just the tilde?)

    im currantly sticking to


    Code:
    path=${path//\~/$HOME}
    because it's in a situation where the user is unlikely to use ~ for anything other than $HOME..
    good to know though, i'll keep it in mind for future use..

    EDIT:

    wow
    I didn't realize bash and sh were that different!
    Last edited by gandalf3; March 28th, 2013 at 07:15 AM. Reason: typo
    Intel Pentium 4 Asus P5N32-SLI DELUXE Nvidia nx7900GT 3GB Ram Western Digital WD2500AAKX 250GB Seagate Barracuda 80GB, 160GB Ubuntu 12.04 Arch

  8. #8
    Join Date
    Jul 2007
    Location
    Poland
    Beans
    4,499
    Distro
    Ubuntu 14.04 Trusty Tahr

    Re: [BASH] tilde doesn't expand from user input?

    sh is more suited for barebone stuff, like running system scripts that are relatively simple and using bash on them would just waste resources. Bash offers goodies that are more useful in userspace scripts. Some people even think bash is bloated

    path=${path/#\~/$HOME} should be good enough in most cases (# forces the pattern to match from the left so eg file~ wont get a substitution). If you think user can have a file with ~filename, you could try doing a test if the file/dir with that exact name exists. If not, assume he meant $HOME and do a replacement, eg
    Code:
    [ -e "$path" ] || path=${path/#\~/$HOME}
    Last edited by Vaphell; March 28th, 2013 at 04:40 PM.
    if your question is answered, mark the thread as [SOLVED]. Thx.
    To post code or command output, use [code] tags.
    Check your bash script here // BashFAQ // BashPitfalls

  9. #9
    Join Date
    Mar 2012
    Location
    the Shire
    Beans
    225
    Distro
    Ubuntu 12.04 Precise Pangolin

    Re: [BASH] tilde doesn't expand from user input?

    I found that it was just easer to do without the read command, instead have a command line argument. now the shell just expands it automatically before the script even gets a hold of it thanks
    Intel Pentium 4 Asus P5N32-SLI DELUXE Nvidia nx7900GT 3GB Ram Western Digital WD2500AAKX 250GB Seagate Barracuda 80GB, 160GB Ubuntu 12.04 Arch

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •