When using the directive source=foobar.sh, then it seems to look up the source relative to the path shellcheck is being run from. For example, I have the following scripts: foo.sh and foobar.sh in the same directory (for example bar/baz from the project root).
Suppose there is the following line in foo.sh:
source "${0%/*}/foobar.sh"
I will get a SC1090 error because shellcheck is unable to resolve the path. I have to do this:
# shellcheck source bar/baz/foobar.sh
source "${0%/*}/foobar.sh"
This works, but only if I run the checker from the project root (either by specifying foo/bar/foobar.sh as an input file, or with -x), but not if I run it from anywhere else. There should be a way to tell shellcheck to look for a file relative to the checked file's location, not where shellcheck is run. For example, this way:
# shellcheck source ./foobar.sh
source "${0%/*}/foobar.sh"
I think generally speaking this is a bad idea which is perhaps why
shellcheck requires you to be explicit about it.
http://mywiki.wooledge.org/BashFAQ/028
I know that $0 is not the best solution to it. I should have used $BASH_SOURCE or something else. But it's besides the point. What I want is to tell ShellCheck where a certain file is located relative to the script. I think it is generally a bad idea to make something work differently (in this case, not work at all) depending on where you run it from.
source foo would also read from the current directory rather than the directory with the script, but I see how that could be useful. Maybe there should be some option to set the directory from which to resolve these paths.
@koalaman I can see the argument that the behaviour as it stands could be useful in some edge cases, but _generally_ I would expect that "resolve relative source= directives from the location of the containing script" would make by far the most sense.
As it currently works (where shellcheck resolves relative source= directives from the location that it is executed from) is a bit surprising and disappointing. It makes it so that there is no good way to ensure that it works when executing shellcheck against a script that contains a relative inclusion (this is not an uncommon occurrence) based off of its own path (using either $0 or $BASH_SOURCE, which is again not exactly unheard of).
I'd claim (at least in my work environment) that this scenario is actually _far_ more common than the environment wherein using the current working directory makes more sense. For us, it is rather unequivocal that the script's parent directory would be a far, far better default.
At the least, I'd like to see a command-line argument to switch behaviours, but I really think that serious thought should be given to making relative links resolve from the script's parent directory, rather than from the current working directory that shellcheck has been executed from.
If directive #shellcheck source= is used then we explicitly say shellcheck where to look for included files, however there is currently no way to make this path relative to the script file itself.
I agree with @rbroemeling and @petersohn currently #shellcheck source= directive is not very usable.
I'm also interested in getting the relative sources to resolve.
source foo would also read from the current directory rather than the directory with the script
If you're worried about existing scripts, you could always make both options explicit. For example:
# shellcheck source=relative/to/pwd
# shellcheck rel-source=relative/to/analysed-script
Actually 'proot' solved my problems enabling me to chroot to the target directory without modifying it and invoke shellcheck as if it was part of the target directory.
In a CI/CD pipeline this isn't an issue, since I control which directory shellcheck is executed from. The issue I have is when using a shellcheck in an IDE. It would be useful to have an argument I can pass to shellcheck to indicate the root path it should use to resolve the directives.
This seems to be a duplicate of #539 — Maybe we should move everything into one place (and possible edit the subject to be easier to find).
@koalaman Wiki for https://github.com/koalaman/shellcheck/wiki/SC1090 is confusing: The path there looks relative. However, if I have 2 files in the same directory (and I get SC1090 on one of them) I cannot write # shellcheck source=./script.bash or # shellcheck source=script.bash on the other one (consistent with this ticket).
"Who is right", "is there any fix coming", "any status update"? (shellcheck 0.6.0 static)
The path is relative, and it's relative to shellcheck's current working directory. It is not relative to the file in which you put this directive.
This presents a problem if i.e. I want to run shellcheck as part of the unit tests, from the top of the project. If I then want to run shellcheck individually while editing a file, the path may be incorrect.
Maybe two (or more) parts could be provided, to account for that?
This really needs to be fixed, makes it a pain to run shellcheck as part of builds, etc, as paths wrt where shellcheck is run can change.
Specifying the path relative to where shellcheck is running from is only realistic for a single user/system. Using # shellcheck source=/dev/null as a workaround seems to be the best approach until this is fixed.
Just because it's hard doesn't mean it can't be improved. The path isn't relative to shellcheck, but rather the current working directory.
Allowing relative paths and/or multiple paths would help for automated builds among other cases.
We also have big problems with source-directive being relative cwd and not script location.
While relative paths would be very useful for resolving this, why not look at the actual root cause: shellcheck not being able to resolve dynamic paths such as these:
source "${0%/*}/foobar.sh"
or
source "${BASH_SOURCE[0]}/foobar.sh"
or
SCRIPT_DIR=$(cd "$(dirname "$(readlink -f "$0")")" || exit 1; pwd)
source "$SCRIPT_DIR/foobar.sh"
That would remove the need for source-directive completely because the only time when we actually need source-directive in the first place is in such scenarios.
It might be runtime code but the pattern is easily identifiable so a small set of special cases could be defined to resolve script directory. Shellcheck could recommend one of them and make sure that source-following works with it. Or shellcheck could bundle a companion-library with built in functions for this.
With 301705edea you can specify -P SCRIPTDIR to search relative to the script's directory, or -P /my/path to search relative to a path in the filesystem. Hopefully this helps!
It would also be simple to make this the default, if that would make things even easier
I recently added shellcheck to my workflow within VS Code (via this extension). As such, shellcheck is called per file. Very helpful in IDE, I tend to jump between several languages/syntax in any given day - Thank you.
In my limited view, I'm thinking #shellcheck source= directive _should attempt to be relative by default:_
shellcheck executable location not likely same as script being checked.My particular instance of SC1090 is (where dotfiles is a repo):
if [ -f "$HOME/dotfiles/1" ];then
. "$HOME/dotfiles/1"
fi
It would be nice if could handle case of $HOME - I rather avoid helper directives in code unless explicitly breaking a rule for a really good reason.
Agreed, -P SCRIPTDIR is great but hard to utilize in IDE.
With 301705e you can specify
-P SCRIPTDIRto search relative to the script's directory, or-P /my/pathto search relative to a path in the filesystem. Hopefully this helps!It would also be simple to make this the default, if that would make things even easier
this is not useful for using shellcheck inside editors. for example vim and syntastic .. Please make the current-script-relative source the default one
With 301705e you can specify
-P SCRIPTDIRto search relative to the script's directory, or-P /my/pathto search relative to a path in the filesystem. Hopefully this helps!
It would also be simple to make this the default, if that would make things even easierthis is not useful for using shellcheck inside editors. for example vim and syntastic .. Please make the current-script-relative source the default one
@drAlberT You can add this line to your .vimrc to pass options to shellcheck w/ syntastic:
[~] $ grep shellcheck .vimrc
let g:syntastic_sh_shellcheck_args = "-x -P SCRIPTDIR"
With 301705e you can specify
-P SCRIPTDIRto search relative to the script's directory, or-P /my/pathto search relative to a path in the filesystem. Hopefully this helps!
It would also be simple to make this the default, if that would make things even easierthis is not useful for using shellcheck inside editors. for example vim and syntastic .. Please make the current-script-relative source the default one
@drAlberT You can add this line to your .vimrc to pass options to shellcheck w/ syntastic:
[~] $ grep shellcheck .vimrc let g:syntastic_sh_shellcheck_args = "-x -P SCRIPTDIR"
My use case is to have relative scripts, not a global wide SCRIPTDIR .. I made a number of different combination of dirs in .vimrc but no luck
Have you any suggestion to add the current SCRIPT dir as SCRIPTDIR on a per file basis ?
I totally did not understand that SCRIPTDIR is a magic value that allows relative-to-script's-directory lookups.
I thought SCRIPTDIR was meant to be "the path to the script's directory".
@docwhat yeah I thought the same thing until I read your comment.
For anyone using SublimeLinter-shellcheck you can add the needed args to the user's SublimeLinter.sublime-settings file, e.g.
// SublimeLinter Settings - User
{
"linters": {
"shellcheck": {
"args": [
"--source-path=SCRIPTDIR",
"--external-sources"
]
}
}
}
Most helpful comment
@koalaman I can see the argument that the behaviour as it stands could be useful in some edge cases, but _generally_ I would expect that "resolve relative
source=directives from the location of the containing script" would make by far the most sense.As it currently works (where shellcheck resolves relative
source=directives from the location that it is executed from) is a bit surprising and disappointing. It makes it so that there is no good way to ensure that it works when executing shellcheck against a script that contains a relative inclusion (this is not an uncommon occurrence) based off of its own path (using either$0or$BASH_SOURCE, which is again not exactly unheard of).I'd claim (at least in my work environment) that this scenario is actually _far_ more common than the environment wherein using the current working directory makes more sense. For us, it is rather unequivocal that the script's parent directory would be a far, far better default.
At the least, I'd like to see a command-line argument to switch behaviours, but I really think that serious thought should be given to making relative links resolve from the script's parent directory, rather than from the current working directory that
shellcheckhas been executed from.