dart2js throwing no such file or directory error - macos

Quite simply, I have a link to dart2js in my /usr/local/bin/ which throws repeated erros when run.
I ran
sudo ln -s /Users/macbook/Development/dart/dart-sdk/bin/dart2js /usr/local/bin/dart2js
When running dart2js from terminal, I'm presented with
...
/usr/local/bin/dart2js: line 9: 1=/Users/macbook/Development/dart/dart-sdk/bin/dart2js: No such file or directory
/usr/local/bin/dart2js: line 9: 1=/Users/macbook/Development/dart/dart-sdk/bin/dart2js: No such file or directory
/usr/local/bin/dart2js: line 9: 1=/Users/macbook/Development/dart/dart-sdk/bin/dart2js: No such file or directory
/usr/local/bin/dart2js: line 9: 1=/Users/macbook/Development/dart/dart-sdk/bin/dart2js: No such file or directory
/usr/local/bin/dart2js: line 9: 1=/Users/macbook/Development/dart/dart-sdk/bin/dart2js: No such file or directory
... etc
I imagine I'm simply using links incorrectly, but I'm not knowledgable enough to know why.

I run into this a while ago and posted this issue Can't run dart command line script using a symlink
I also added a workaround which may help in your situation as well - you probably need to adapt it a bit but it should get you started.
A workaround I use now is to create a bash script named 'testscript' in the same directory as testscript.dart and link to this script instead
I lookup the current directory of the bash script and start the dart script
(Getting the source directory of a Bash script from within).
#!/bin/bash
ME="$(basename "$(test -L "$0" && readlink "$0" || echo "$0")")"
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
${DIR}/${ME}.dart ${BASH_SOURCE[0]}
Instead of getting the command's (symlinks) name with io.Platform.script I have to pass it as an argument to have it available inside the dart script (I use the name of the symlink used to start the script like an argument inside the dart script)
This way I have to distinguish if the script was started directly and use io.Platform.script and args[0] otherwise.
I think this should all be easier.

Related

Bad substitution error in shell script while extracting directory [duplicate]

This question already has answers here:
Difference between sh and Bash
(11 answers)
Closed 6 months ago.
I am getting bad substitution error on running the following shell script. (Line numbers written just for reference):
Line 11> SCENARIO_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
Line 12> SCENARIO_PATH="${SCENARIO_DIR}/scenarios"
The error in TeamCity is
| ./k6-run-all.sh: line 12: syntax error: bad substitution
Please note that on running this in local, I do not get this error and the scenario path is correctly extracted. But when I run this on TeamCity (which runs on Docker) it is giving me the above error.
Scenario path in my local is: /Users/sonaliagrawal/Documents/antman/src/scenarios/full-card-visa
Scenario path in TeamCity is extracting correctly despite the error which is:
//scenarios/full-card-visa
Solution tried:
Since in TeamCity, SCENARIO_DIR is itself just / hence I wrote an if then else to handle it, but it didn't help solve the substitution error, it just corrected the path to /scenarios/full-card-visa. The code I had added is as follows-
SCENARIO_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
echo "Scenario directory $SCENARIO_DIR"
SCENARIO_PATH=""
if [[ "$SCENARIO_DIR" = "/" ]]; then
SCENARIO_PATH="/scenarios"
else
SCENARIO_PATH="${SCENARIO_DIR}/scenarios"
fi
Reference:
In case it helps, Dockerfile is as follows:
FROM loadimpact/k6:0.34.1
COPY ./src/lib /lib
COPY ./src/scenarios /scenarios
COPY ./src/k6-run-all.sh /k6-run-all.sh
WORKDIR /
ENTRYPOINT []
CMD ["sh", "-c", "./k6-run-all.sh"]
It's because your script isn't being executed as a bash script. Put the following on the top of the .sh file.
#!/bin/bash

Bash relative path to absolute path [duplicate]

I have written a Bash script that takes an input file as an argument and reads it.
This file contains some paths (relative to its location) to other files.
I would like the script to go to the folder containing the input file, to execute further commands.
In Linux, how do I get the folder (and just the folder) from an input file?
To get the full path use:
readlink -f relative/path/to/file
To get the directory of a file:
dirname relative/path/to/file
You can also combine the two:
dirname $(readlink -f relative/path/to/file)
If readlink -f is not available on your system you can use this*:
function myreadlink() {
(
cd "$(dirname $1)" # or cd "${1%/*}"
echo "$PWD/$(basename $1)" # or echo "$PWD/${1##*/}"
)
}
Note that if you only need to move to a directory of a file specified as a relative path, you don't need to know the absolute path, a relative path is perfectly legal, so just use:
cd $(dirname relative/path/to/file)
if you wish to go back (while the script is running) to the original path, use pushd instead of cd, and popd when you are done.
* While myreadlink above is good enough in the context of this question, it has some limitation relative to the readlink tool suggested above. For example it doesn't correctly follow a link to a file with different basename.
Take a look at realpath which is available on GNU/Linux, FreeBSD and NetBSD, but not OpenBSD 6.8. I use something like:
CONTAININGDIR=$(realpath ${FILEPATH%/*})
to do what it sounds like you're trying to do.
This will work for both file and folder:
absPath(){
if [[ -d "$1" ]]; then
cd "$1"
echo "$(pwd -P)"
else
cd "$(dirname "$1")"
echo "$(pwd -P)/$(basename "$1")"
fi
}
$cat abs.sh
#!/bin/bash
echo "$(cd "$(dirname "$1")"; pwd -P)"
Some explanations:
This script get relative path as argument "$1"
Then we get dirname part of that path (you can pass either dir or file to this script): dirname "$1"
Then we cd "$(dirname "$1"); into this relative dir
pwd -P and get absolute path. The -P option will avoid symlinks
As final step we echo it
Then run your script:
abs.sh your_file.txt
Try our new Bash library product realpath-lib over at GitHub that we have given to the community for free and unencumbered use. It's clean, simple and well documented so it's great to learn from. You can do:
get_realpath <absolute|relative|symlink|local file path>
This function is the core of the library:
if [[ -f "$1" ]]
then
# file *must* exist
if cd "$(echo "${1%/*}")" &>/dev/null
then
# file *may* not be local
# exception is ./file.ext
# try 'cd .; cd -;' *works!*
local tmppwd="$PWD"
cd - &>/dev/null
else
# file *must* be local
local tmppwd="$PWD"
fi
else
# file *cannot* exist
return 1 # failure
fi
# reassemble realpath
echo "$tmppwd"/"${1##*/}"
return 0 # success
}
It's Bash 4+, does not require any dependencies and also provides get_dirname, get_filename, get_stemname and validate_path.
Problem with the above answer comes with files input with "./" like "./my-file.txt"
Workaround (of many):
myfile="./somefile.txt"
FOLDER="$(dirname $(readlink -f "${ARG}"))"
echo ${FOLDER}
I have been using readlink -f works on linux
so
FULL_PATH=$(readlink -f filename)
DIR=$(dirname $FULL_PATH)
PWD=$(pwd)
cd $DIR
#<do more work>
cd $PWD

Source another shell script relative to current script path without $0

I wonder if there's a good way to source another shell script without $(basename "$0") solution, since sometimes "$0" is not set.
For exmaple "$0" would be "-sh" for login shell.
There's same problem with regard to cwd solution.
You could use this expression to find out the directory of the parent Bash script:
dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
Then you can call your script like this:
cd $dir; source ./other_script
or
source $dir/other_script
See this related post: Getting the source directory of a Bash script from within

How to change current working directory inside command_not_found_handle

I'm trying to write a not found handle in Bash that does the following:
If $1 exists and it's a directory, cd into it.
If $1 exists inside a user defined directory $DEV_DIR, `cd into it.
If the previous conditions don't apply, fail.
Right now I have something like this:
export DEV_DIR=/Users/federico/programacion/
function command_not_found_handle () {
if [ -d $1 ]; then # the dir exists in '.'
cd $1
else
to=$DEV_DIR$1
if [ -d $to ]; then
cd $to
echo `pwd`
else
echo "${1}: command not found"
fi
fi
}
And although it seems to be working (the echo pwd command prints the expected dir), the directory in the actual shell does not change.
I was under the impression that since this is a function inside my .bashrc the shell wouldn't fork and I could do the cd but apparently that's not working. Any tips on how to solve this would be appreciated.
I think what's going on is that the shell fork()s after setting up any redirections but before looking for commands, so command_not_found_handle can't affect the interactive shell process.
What you seem to want to do may partly possible using the autocd feature:
shopt -s autocd
From man bash:
autocd - If set, a command name that is the name of a directory
is executed as if it were the argument to the cd com‐
mand. This option is only used by interactive shells.
Otherwise, just create a function that you invoke by name that performs the actions you are trying to use command_not_found_handle for.
It won't change directies if you run this program as a script in your main shell because it creates a sub-shell when it executes. If you source the script in your current shell then it will have the desired effect.
~/wbailey> source command_not_found.sh
That said, I think the following would achieve the same result:
wesbailey#feynman:~/code_katas> cd xxx 2> /dev/null || cd ..; pwd
/Users/wesbailey
just replace the ".." with your env var defined directory and create an alias in your .bashrc file.
I've had the very same wish and the solution that I've been using for a while was opening a new tab in gnome terminal by issuing the command gnome-terminal --tab --working-directory="$FOLDER" from inside the command_not_found handle.
But today I've come up with a solution which is not tied to a specific terminal application, but has exactly the intended behaviour.
The solution uses the PROMPT_COMMAND, which is run before each prompt. The PROMPT_COMMAND is bound to a function responsible for checking for a file related to current shell, and cd'ing into the directory specified in that file.
Then, the command_not_found_handle fills in the file when a change in directory is desired. My original command_not_found_handle also checkout a git branch if the current directory is a git repository and the name matches an existing branch. But to keep focus on answering the current question, I've stripped that part of code.
The command_not_found_handle uses find for searching for the directory matching the given name and goes only 2 levels deep in the directory tree, starting from a configured list.
The code to be added to bash_rc follows:
PROMPT_COMMAND=current_shell_cd
CD_FILE="${XDG_CACHE_HOME:-$HOME/.cache}/bash-cd/$$.cd"
current_shell_cd() {
if [ -r "$CD_FILE" ]; then
local CD_TARGET="$( cat "$CD_FILE" )"
[ ! -z "$CD_TARGET" ] && cd "$CD_TARGET" 2>/dev/null
rm "$CD_FILE"
fi
}
command_not_found_handle () {
local COMMAND="$1";
# List folders which are going to be checked
local BASE_FOLDER_LIST=(
"$HOME/Desenvolvimento"
"/var/www/html"
"$HOME/.local/opt/"
)
local FOLDER=$(
find "${BASE_FOLDER_LIST[#]}" \
-maxdepth 2 -type d \
-iname "$COMMAND" -print -quit )
if [ ! -z "$FOLDER" -a -d "$FOLDER" ]
then
mkdir -p "$( dirname "$CD_FILE" )"
echo "$FOLDER" > "$CD_FILE"
else
printf "%s: command not found\n" "$1" 1>&2
return 127
fi
}

How can I set the current working directory to the directory of the script in Bash?

I'm writing a Bash script. I need the current working directory to always be the directory that the script is located in.
The default behavior is that the current working directory in the script is that of the shell from which I run it, but I do not want this behavior.
#!/bin/bash
cd "$(dirname "$0")"
The following also works:
cd "${0%/*}"
The syntax is thoroughly described in this StackOverflow answer.
Try the following simple one-liners:
For all UNIX/OSX/Linux
dir="$(cd -P -- "$(dirname -- "$0")" && pwd -P)"
Bash
dir="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
Note: A double dash (--) is used in commands to signify the end of command options, so files containing dashes or other special characters won't break the command.
Note: In Bash, use ${BASH_SOURCE[0]} in favor of $0, otherwise the path can break when sourcing it (source/.).
*For Linux, Mac and other BSD:
cd "$(dirname "$(realpath -- "$0")")";
Note: realpath should be installed in the most popular Linux distribution by default (like Ubuntu), but in some it can be missing, so you have to install it.
Note: If you're using Bash, use ${BASH_SOURCE[0]} in favor of $0, otherwise the path can break when sourcing it (source/.).
Otherwise you could try something like that (it will use the first existing tool):
cd "$(dirname "$(readlink -f -- "$0" || realpath -- "$0")")"
For Linux specific:
cd "$(dirname "$(readlink -f -- "$0")")"
*Using GNU readlink on BSD/Mac:
cd "$(dirname "$(greadlink -f -- "$0")")"
Note: You need to have coreutils installed
(e.g. 1. Install Homebrew, 2. brew install coreutils).
In bash
In bash you can use Parameter Expansions to achieve that, like:
cd "${0%/*}"
but it doesn't work if the script is run from the same directory.
Alternatively you can define the following function in bash:
realpath () {
[[ "$1" = /* ]] && echo "$1" || echo "$PWD/${1#./}"
}
This function takes 1 argument. If argument has already absolute path, print it as it is, otherwise print $PWD variable + filename argument (without ./ prefix).
or here is the version taken from Debian .bashrc file:
function realpath()
{
f=$#
if [ -d "$f" ]; then
base=""
dir="$f"
else
base="/$(basename -- "$f")"
dir="$(dirname -- "$f")"
fi
dir="$(cd -- "$dir" && /bin/pwd)"
echo "$dir$base"
}
Related:
How to detect the current directory in which I run my shell script?
How do I get the directory where a Bash script is located from within the script itself?
Bash script absolute path with OS X
Reliable way for a Bash script to get the full path to itself
See also:
How can I get the behavior of GNU's readlink -f on a Mac?
cd "$(dirname "${BASH_SOURCE[0]}")"
It's easy. It works.
The accepted answer works well for scripts that have not been symlinked elsewhere, such as into $PATH.
#!/bin/bash
cd "$(dirname "$0")"
However if the script is run via a symlink,
ln -sv ~/project/script.sh ~/bin/;
~/bin/script.sh
This will cd into the ~/bin/ directory and not the ~/project/ directory, which will probably break your script if the purpose of the cd is to include dependencies relative to ~/project/
The symlink safe answer is below:
#!/bin/bash
cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" # cd current directory
readlink -f is required to resolve the absolute path of the potentially symlinked file.
The quotes are required to support filepaths that could potentially contain whitespace (bad practice, but its not safe to assume this won't be the case)
This script seems to work for me:
#!/bin/bash
mypath=`realpath $0`
cd `dirname $mypath`
pwd
The pwd command line echoes the location of the script as the current working directory no matter where I run it from.
There are a lot of correct answers in here, but one that tends to be more useful for me (making sure a script's relative paths remain predictable/work) is to use pushd/popd:
pushd "$(dirname ${BASH_SOURCE:0})"
trap popd EXIT
# ./xyz, etc...
This will push the source file's directory on to a navigation stack, thereby changing the working directory, but then, when the script exits (for whatever reason, including failure), the trap will run popd, restoring the current working directory before it was executed. If the script were to cd and then fail, your terminal could be left in an unpredictable state after the execution ends - the trap prevents this.
I take this and it works.
#!/bin/bash
cd "$(dirname "$0")"
CUR_DIR=$(pwd)
Get the real path to your script
if [ -L $0 ] ; then
ME=$(readlink $0)
else
ME=$0
fi
DIR=$(dirname $ME)
(This is answer to the same my question here: Get the name of the directory where a script is executed)
cd "`dirname $(readlink -f ${0})`"
Most answers either don't handle files which are symlinked via a relative path, aren't one-liners or don't handle BSD (Mac). A solution which does all three is:
HERE=$(cd "$(dirname "$BASH_SOURCE")"; cd -P "$(dirname "$(readlink "$BASH_SOURCE" || echo .)")"; pwd)
First, cd to bash's conception of the script's directory. Then readlink the file to see if it is a symlink (relative or otherwise), and if so, cd to that directory. If not, cd to the current directory (necessary to keep things a one-liner). Then echo the current directory via pwd.
You could add -- to the arguments of cd and readlink to avoid issues of directories named like options, but I don't bother for most purposes.
You can see the full explanation with illustrations here:
https://www.binaryphile.com/bash/2020/01/12/determining-the-location-of-your-script-in-bash.html
echo $PWD
PWD is an environment variable.
If you just need to print present working directory then you can follow this.
$ vim test
#!/bin/bash
pwd
:wq to save the test file.
Give execute permission:
chmod u+x test
Then execute the script by ./test then you can see the present working directory.

Resources