1

I have hundreds of sub-directories which contain a dollar sign (i.e., $) as the 1st character in their names, each of which needs to be visited. These sub-directories can not be renamed. The bash script function tries to visit each and (so far) to echo the path its in. Trying to do this via a built path string then eval it.

The line that print cmd=${cmd} indeed shows cmd=cd /rbyoko/c/$Ono.RCB as expected - however, the eval command mis-interprets the $Ono.RCB (probably as $Ono being empty var) and results in: -bash: cd: /rbyoko/c/.BIN/: No such file or directory then the following line prints We are in /home/user (where the script was run from).

My question: how do I eval the string (and/or escape the sub-directory with $) to actually succeed in visiting the desired sub-directory?

Here is my function:

visit_tree_recbin()
{
            strings="cdhlotpw"
            MACHINE=`uname -a`
            PWD=`pwd`
            for i in $(seq 1 ${#strings})
            do
                c="${strings:i-1:1}"
                echo "Letter $i: $c"
                #build eval string to do: cd "/rbyoko/${c}/\$Ono.RCB/"
                x1="cd /rbyoko/${c}/"
                x2="\$"
                x3="Ono.RCB/"
                cmd="${x1}${x2}${x3}"
                echo "cmd=${cmd}"
                eval "${x1}${x2}${x3}"
                echo "We are in " `pwd`
            done
}
3
  • Are you sure the problem isn't the assignment x2="\$"? Try x2="\\$" or x2='\$' if you want to preserve the literal value of the backslash Dec 11, 2018 at 18:46
  • Yes, that's it....the x2="\\$" fixed the issue, thanks !
    – BazukaJoe
    Dec 11, 2018 at 18:58
  • Note that PWD is a variable that already contains the current working directory.
    – Kusalananda
    Dec 12, 2018 at 7:51

1 Answer 1

1

Don't try run commands stored in variables (unless it's just a simple command name and/or path). It is bound to fail in interesting ways unless you get the quoting right (which can be fiddly and lead to less robust code).

In your case, it would be enough with

cd "/rbyoko/$c/\$Ono.RCB"

i.e. quote the directory pathname (to allow for $c to have whitespaces) and then escape the $.

Alternatively:

cd "/rbyoko/$c"/'$Ono.RCB'

i.e. single quote the bit with the dollar sign to protect it from the shell.

Your function, modified:

visit_tree_recbin () {
    for dir in c d h l o t p w; do
            cd "/rbyoko/$dir"/'$Ono.RCB'
            printf 'We are now in %s\n' "$PWD"
    done
}

Alternatively,

visit_tree_recbin () {
    for dirpath in /rbyoko/[cdhlotpw]/'$Ono.RCB'/; do
            cd "$dirpath"
            printf 'We are now in %s\n' "$PWD"
    done
}

The difference is that the first variation will create directory pathnames and cd into these. This may fail if the directory does not exist.

The second variation uses a filename globbing pattern that matches existing directories. If the pattern matches anything, the cd will succeed (if you have permission to cd into the directory).

Note that bash maintains a PWD variable that contains the pathname of the current working directory, so there's no need to use pwd here.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .