Shellcheck: source directive is relative to current working directory (CWD)

Created on 5 Nov 2015  路  7Comments  路  Source: koalaman/shellcheck

If I have file bar who references foo in the same directory. However if I run bar from somewhere else than its own directory, source fails, that's why I add a ENV variable. Below is a small example

# shellcheck source=foo.sh
. $SOME_ENV_DIR/foo.sh

I run $ shellcheck foo.sh bar.shand everything works fine. However if I run shellcheck from a different directory it fails, basically shellcheck does the same as bash i.e. the source=bar.sh directive is taken relative to CWD.

I expected this to work because due to transitivity in this example foo could be sourced by a 3rd file from a different directory and I'd like to be able to shellcheck from its directory as well.
The dir structure would then be:

 |- foo.sh                        
 |- bar.sh                   # source=foo.sh
 |- directory \
              |- 3rdfile.sh # source=../bar.sh

Is the "appropriate" way to assume some single root and make every reference relative to that? That would make it quite inflexible though.

Most helpful comment

Hi -- I am indeed using $(dirname "${BASH_SOURCE[0]}") to refer to scripts in the same directory, but I don't see how I can express this with source. Would you consider adding a relsource or similar directive for this common pattern?

All 7 comments

I think this is mostly a duplicate of #500 and #510.

That said a bash script can (and probably should for cases like this) use something like this SO answer and/or Bash FAQ 028 instead of assuming $PWD or requiring a specific environment variable.

Hi -- I am indeed using $(dirname "${BASH_SOURCE[0]}") to refer to scripts in the same directory, but I don't see how I can express this with source. Would you consider adding a relsource or similar directive for this common pattern?

Any update on this? It'd be much better than having to turn off the checker.

Here is a suggestion for how to implement this:

  • For paths that begin with /, the actual path is ${RootPath}/${SourceOverride} (don't know the Haskell syntax, sorry).
  • For paths that begin with ./, the actual path is ${DirectoryOfScript}/${SourceOverride}
  • For paths that begin with anything else, it behaves as-is.

The code can determine the RootPath by:

  • A command line argument (e.g., --root=<RootPath> as suggested in #510
  • By looking for a project root indicator such as .projectroot, .git, .hg, .svn, .bzr, _darcs, build.xml.

    I tried looking for a Haskell package to determine a project's root, but didn't find anything.

  • As ultimate fallback, use the current directory.

I tried to read the code in Parser.hs for the method getSourceOverride but I know pretty much zero Haskell.

Can anyone suggest something to get me started? I'm familiar with some functional concepts but am rusty on things like Monads, Maybes, etc.

The action would most likely be in Parser.hs readSource where the filename is passed as-is in system $ siReadFile sys filename . The filename would need to be transformed based on a directory passed in the Environment (like shellTypeOverride).

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!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

maxisme picture maxisme  路  3Comments

quchen picture quchen  路  3Comments

balloonpopper picture balloonpopper  路  4Comments

ymkjp picture ymkjp  路  3Comments

sobolevn picture sobolevn  路  4Comments