5 ms·
Really minimal template, that works well for all scenarios and doesn't cause unexpected behaviour (like changing IFS does): #!/usr/bin/env bash se
by fn1 6y ago
Really minimal template, that works well for all scenarios and doesn't cause unexpected behaviour (like changing IFS does):
#!/usr/bin/env bash
set -eEu -o pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
reference all relative things with dir first:
"$DIR/relativestuff.sh"
- nerdponx 6y agoEvery time I see this I can't help but smile, knowing that in Zsh the equivalent code is: #!/usr/bin/env zsh setopt err_exit no_unset DIR=${0:h}
- lukeschlather 6y agoHonestly I think I prefer the bash version to `DIR=${0:h}`. Although Powershell is superior with simply "$PSScriptRoot" (On the other hand, Powershell's strict mode is a mess and "catch errors" in Powershell is still an extra setting that doesn't actually catch errors half the time.)
- rhencke 6y agoIf you like that, you'll love working with PowerShell's exit codes. [1] [2] [3] [1] https://weblogs.asp.net/soever/returning-an-exit-code-from-a-powershell-script https://weblogs.asp.net/soever/returning-an-exit-code-from-a... [2] https://octopus.com/blog/powershell-exit-codes https://octopus.com/blog/powershell-exit-codes [3] https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/correctly-returning-exit-codes https://community.idera.com/database-tools/powershell/powert...
- nerdponx 6y agoOut of curiosity, what do you like better about the Bash version?
- kwhitefoot 6y agoNot the OP. For the occasional user, like me, it is more obvious what it is doing.
- michaelmior 6y agoI much prefer this approach (finding the script directory and explicitly using it) over changing into the directory of the script. It makes it much easier to use paths relative to the working directory when you want to.
- uhtred 6y agoOut of interest, why is the way you are handling relative paths better?
- deleted 6y ago[deleted]
- weitzj 6y agoOr add a popd $DIR
- tpoacher 6y agois there a reason "cd && pwd" is preferred over `realpath`?
- Hello71 6y agomac doesn't have realpath command.
- pstuart 6y agoor a modern bash built in (grrrr)
- gabagool 6y agoIn fairness, macOS has switched over to zsh as of 1 year ago in macOS Catalina: https://support.apple.com/en-us/HT208050 https://support.apple.com/en-us/HT208050. Catalina shipped with zsh 5.7 whereas 5.8 is now the latest.
- jen20 6y agoBig Sur ships with zsh 5.8 as /bin/zsh.
- fomine3 6y agoWhat about to use zsh to run bash script on mac? Possibly it's better than old bash.
- latexr 6y agoThat may cause errors or undesirable behaviour. As way of example, dealing with arrays: `read -a` in bash is `read -A` in zsh, and the former’s arrays are zero-based while the latter’s are one-based.
- pstuart 6y agoMy gripe is about being able to work on a bash script that needs to work "everywhere". Bash 4 was release over a decade ago, so it's a reasonable expectation that it will be present on most servers with a shell. Homebrew works around that, but their refusal over GPL taint for having the binary present still doesn't seem right.
- mongol 6y agoI like the readlink command
- rashkov 6y agoSame, I was scratching my head, wondering why the author of the article doesn't just use readlink... and then a few hours later, a coworker of mine asked why my bash script isn't working on her Mac! Turns out readlink on OS X doesn't have the same flags. I ended up substituting it out for the hackier but more portable method that the article uses.
- fn1 6y ago...also use shellcheck
- 0xbadcafebee 6y agoThis is the real minimal template. But it should be pwd -P at the end there or you introduce path resolving bugs. Or you could use cd -P, or cd -e -P to be extra fail-safe (bashism). I also tack on [ "${DEBUG:-0}" = "1" ] && set -x
- idolaspecus 6y agoIMO this solution solves the wrong problem. The “right” problem to solve is the coupling between the script and the directory layout. If the script needs to operate on data in some directory, the path to that directory should be part of the script’s interface and handled accordingly.
- da39a3ee 6y agoWhat about if the script wants to source sibling files in the samedirectory? I.e. it is a bash library of sorts with modules spread over files. This isn’t “operating on data” abe it would be weird for a library to have to receive its own location as an argument in order to have to load its own modules.
- idolaspecus 6y agoI don't think there's much weird about providing a script a path to its dependencies. If it's the case that the path to the dependencies location is the same as the path to the script's location, that's fine. We're asking distinct questions (where is my data, where are my deps, where is my script) here, the unnecessary coupling is precisely the assumption they have the same answer. If they happen to have the same answer, that's not weird, that sort of thing happens all the time.
- beefbroccoli 6y agoIn many cases one might not want a full stand-alone program with arguments, usage and such. Rather a "script" i.e. something that can be simply executed to run a series of tasks. For example it's quite silly for a build script to require the path of the project it resides in.
- idolaspecus 6y agoIt's really not silly. A build script could easily move around inside a project. It could go from the project root, to /root/bin, to /root/bin/build, etc etc. If the inconvenience of arguments troubles you, write a wrapper or alias it or something like that.