0

I am having a problem with this.

If I do...

source /Users/cristian/Proyectos/MikroTik\ Updater/sources/testfile

It does work

If I do...

source "/Users/cristian/Proyectos/MikroTik\ Updater/sources/testfile"

It doesn’t

The problem is that I’m using a variable which contains a path got some steps before

So this...

mypath="/Users/cristian/Proyectos/MikroTik\ Updater/sources/testfile"
source $mypath

Doesn’t work neither

I found a workaround doin...

eval "source $mypath"

But of course it is a big security hole because file name comes from an argument

What can I do?

EDIT:

As you can see in the code I echo the filename and then try to source it

updaterpath="$( cd "$(dirname "$0")" ; pwd -P | sed  's/ /\\ /g' )"
sourcefile="$updaterpath/sources/$1"

echo $sourcefile
source $sourcefile

In the output I get the correct path echoed and the error from source saying it doesn't exists! The funny thing is that whether I cat that file, I can see the content, so the file path is correct!

/Users/cristian/Proyectos/MikroTik\ Updater/sources/testfile
/Users/cristian/Proyectos/MikroTik Updater/updater.sh: line 7: /Users/cristian/Proyectos/MikroTik\: No such file or directory
11
  • 4
    ShellCheck points out that you're using unicode slanted quotes instead of ascii quotes " Commented Apr 25, 2018 at 19:09
  • 2
    What is the actual path? Absent characters that require quoting, there is literally no difference bretween source /path/to/file and source "/path/to/file"; the quotes are removed by the shell before source is executed. Commented Apr 25, 2018 at 19:56
  • 3
    Oh -- you have literal backslashes in your path. Yeah, that explains the problem. Commented Apr 25, 2018 at 20:03
  • 3
    Basically, you should never, ever try to use sed to escape a path. Commented Apr 25, 2018 at 20:03
  • 1
    BTW, see BashFAQ #28 re: why $0 is unreliable for finding your script location. Commented Apr 25, 2018 at 20:11

2 Answers 2

4

Your original question didn't include the faulty code:

### THIS IS BROKEN: the backslashes added by sed are literal, not syntactic
path=$(cd "$(dirname "$0")"; pwd -P | sed 's/ /\\ /g')
source $path/sources/$1

The sed is the source of your problem. Just get rid of it:

### THIS IS CORRECT: The syntactic quotes mean no backslashes are needed.
# ...also handles the case when the cd fails more gracefully.
path=$(cd "$(dirname "$0")" && pwd -P) || exit
source "$path/sources/$1"

...or, even better:

source "${BASH_SOURCE%/*}/sources/$1"

Backslashes are only meaningful when parsed as syntax. Results of string expansion do not go through these parsing steps. This is the same reason literal quotes can't be used to build a command in a string, as discussed in BashFAQ #50.

Sign up to request clarification or add additional context in comments.

1 Comment

I ended up using sed after trying some stuff and the bug stayed there! Now I have removed sed and did source "$sourcefile" which worked! Sometimes, after some hours of work, what one just needs is a pair of additional eyes! Thanks!!
0

The code stayed this way if someone needs to see it

updaterpath="$( cd "$(dirname "$0")" ; pwd -P )"
sourcefile="$updaterpath/sources/$1"

echo $sourcefile
source "$sourcefile"

2 Comments

As an aside, it'd be advisable to quote the argument to echo, as in echo "$sourcefile". Otherwise, there are some changes between the actual command and the command-as-displayed that could be lost -- for instance, your filename has spaces; if it had two spaces in a row, the unquoted expansion would only show one. If the name contained a whitespace-surrounded *, the unquoted version would replace that with a list of files in the current directory. Etc.
(to explain why those effects happen -- when the expansion isn't quoted, the name is broken up into individual words, and then each of those words is evaluated as a glob expression, before passing the results as an array of C strings to echo, which puts a single space between each argument, not having any way to know how many spaces were there originally).