I have the following script:
#!/bin/bash
set -o errexit # Exit on error
# Enable script to run from anywhere
root="$(dirname ${BASH_SOURCE[0]})"
cd "$($root)"
source ./scripts/main
cd "$($root)"
pwd
source ./scripts/test
cd "$($root)/applicant"
yarn build
But I get this error:
./build.sh: line 8: .: filename argument required
How can I get a variable of the current directory?
you can use pwd for current directory.
-61T9:~ pwd
/Users/test
-61T9:~ s=`pwd`
-61T9:~ echo $s
/Users/test
You can do it simply:
cd $variable_with_path
In your example you should replace "$($root)" by $root
To get variable with current directory:
path=`pwd`
Related
I've copied a script from the unifi documentation
#!/bin/sh
## define required variables
username=admin
password=admin
baseurl=https://localhost:8443
## include the API library
. unifi_sh_api
unifi_login
# unifi_authorize_guest <mac> <minutes> [up=kbps] [down=kbps] [bytes=MB]
unifi_authorize_guest $1 $2
unifi_logout
This is the script and this is the file structure:
foo#site:/home/foo# ls
unifi.sh unifi_sh_api
This is what I get when I try to execute the file. What can cause this? The file is obviously in the right folder.
foo#site:/home/foo# sh unifi.sh
unifi.sh: 9: .: unifi_sh_api: not found
You are invoking bash as /bin/sh which puts bash into sh-compatibility mode. The POSIX standard says that:
If file does not contain a slash, the shell shall use the search path specified by PATH to find the directory containing file.
Which means that the current directory will not be searched unless it is part of $PATH:
$ /bin/sh -c '. test.sh'
/bin/sh: 1: .: t.sh: not found
$ /bin/sh -c 'PATH=".:$PATH"; . test.sh'
$
bash, however, seems to search the current directory:
$ /bin/bash -c '. test.sh'
$
This question already has answers here:
Why can't I change directories using "cd" in a script?
(33 answers)
Closed 7 years ago.
What I'm trying to do
I've created a shell script that I've added to my $PATH that will download and get everything setup for a new Laravel project. I would like the script to end by changing my terminal directory into the new project folder.
From what I understand right now currently it's only changing the directory of the sub shell where the script is actually running. I can't seem to figure out how to do this. Any help is appreciated. Thank you!
#! /usr/bin/env bash
echo -e '\033[1;30m=========================================='
## check for a directory
if test -z "$1"; then
echo -e ' \033[0;31m✖ Please provide a directory name'
exit
fi
## check if directory already exist
if [ ! -d $1 ]; then
mkdir $1
else
echo -e ' \033[0;31m✖ The '"$1"' directory already exists'
exit
fi
# move to directory
cd $1
## Download Laravel
echo -e ' \033[0;32m+ \033[0mDownloading Laravel...'
curl -s -L https://github.com/laravel/laravel/zipball/master > laravel.zip
## Unzip, move, and clean up Laravel
echo -e ' \033[0;32m+ \033[0mUnzipping and cleaning up files...'
unzip -q laravel.zip
rm laravel.zip
cd *-laravel-*
mv * ..
cd ..
rm -R *-laravel-*
## Make the /storage directory writable
echo -e ' \033[0;32m+ \033[0mMaking /storage directory writable...'
chmod -R o+w storage
## Download and install the Generators
echo -e ' \033[0;32m+ \033[0mInstalling Generators...'
curl -s -L https://raw.github.com/JeffreyWay/Laravel-Generator/master/generate.php > application/tasks/generate.php
## Update the application key
echo -e ' \033[0;32m+ \033[0mUpdating Application Key...'
MD5=`date +”%N” | md5`
sed -ie 's/YourSecretKeyGoesHere!/'"$MD5"'/' application/config/application.php
rm application/config/application.phpe
## Create .gitignore and initial git if -git is passed
if [ "$2" == "-git" ]; then
echo -e ' \033[0;32m+ \033[0mInitiating git...'
touch .gitignore
curl -s -L https://raw.github.com/gist/4223565/be9f8e85f74a92c95e615ad1649c8d773e908036/.gitignore > .gitignore
# Create a local git repo
git init --quiet
git add * .gitignore
git commit -m 'Initial commit.' --quiet
fi
echo -e '\033[1;30m=========================================='
echo -e ' \033[0;32m✔ Laravel Setup Complete\033[0m'
## Change parent shell directory to new directory
## Currently it's only changing in the sub shell
filepath=`pwd`
cd "$filepath"
You can technically source your script to run it in your parent shell instead of spawning a subshell to run it. This way whatever changes you make to your current shell (including changing directories) persist.
source /path/to/my/script/script
or
. /path/to/my/script/script
But sourcing has its own dangers, use carefully.
(Peripherally related: how to use scripts to change directories)
Use a shell function to front-end your script
setup () {
# first, call your big script.
# (It could be open-coded here but that might be a bit ugly.)
# then finally...
cd someplace
}
Put the shell function in a shell startup file.
Child processes (including shells) cannot change current directory of parent process. Typical solution is using eval in the parent shell. In shell script echo commands you want to run by parent shell:
echo "cd $filepath"
In parent shell, you can kick the shell script with eval:
eval `sh foo.sh`
Note that all standard output will be executed as shell commands. Messages should output to standard error:
echo "Some messages" >&2
command ... >&2
This can't be done. Use exec to open a new shell in the appropriate directory, replacing the script interpreter.
exec bash
I suppose one possibility would be to make sure that the only output of your script is the path name you want to end up in, and then do:
cd `/path/to/my/script`
There's no way your script can directly affect the environment (including it's current directory) of its parent shell, but this would request that the parent shell itself change directories based on the output of the script...
I have the following script sample:
#!/bin/bash
# Aborts the script on "simple command failure" (does not cover pipes)
set -e
# Makes sure we do not run the script outside the correct directory (i.e. the backup directory)
projects_directory='~/projects'
backup_drectory="${projects_directory}/backup/"
echo "Backup directory: ${backup_drectory}"
if [ ! -d "$projects_directory" ]; then
mkdir "$projects_directory"
echo "${projects_directory} created successfully"
fi
Which fails miserably with the following output:
Backup directory: ~/projects/backup/
mkdir: cannot create directory `~/projects': No such file or directory
I do not understand why. If I enter the mkdir ~/projects command manually in a Terminal, the directory gets created. Any suggestion is most welcome.
Remove the single quotes:
projects_directory=~/projects
The quoting prevents the shell from expanding the ~ character.
When I change into a directory with the cd command, I lose the previous working directory, unless I remember it in my memory. Is there some handy method to go back quickly?
Demo:
$ cd ~/some_path
$ cd /another_path
$ command_to_go_back_to_some_path
You can go back to the last dir with cd -
You can also do this
$ pushd ~/some_path
$ pushd /another_path
$ popd
$ popd
As mentioned you can use cd -. The shell internally does a cd $OLDPWD.
For usage in a script, you could use the OLDPWD shell variable: it contains the previous working directory.
$ pwd
/home/username
$ cd /usr/bin
$ pwd
/usr/bin
$ cd "$OLDPWD"
$ pwd
/home/username
I prefer this over cd - in scripts because I don't have to suppress any output.
If you want to use it in a script and suppress the output, do this:
cd - > /dev/null
I am attempting to write a bash script that changes directory and then runs an existing script in the new working directory.
This is what I have so far:
#!/bin/bash
cd /path/to/a/folder
./scriptname
scriptname is an executable file that exists in /path/to/a/folder - and (needless to say), I do have permission to run that script.
However, when I run this mind numbingly simple script (above), I get the response:
scriptname: No such file or directory
What am I missing?! the commands work as expected when entered at the CLI, so I am at a loss to explain the error message. How do I fix this?
Looking at your script makes me think that the script you want to launch a script which is locate in the initial directory. Since you change you directory before executing it won't work.
I suggest the following modified script:
#!/bin/bash
SCRIPT_DIR=$PWD
cd /path/to/a/folder
$SCRIPT_DIR/scriptname
cd /path/to/a/folder
pwd
ls
./scriptname
which'll show you what it thinks it's doing.
I usually have something like this in my useful script directory:
#!/bin/bash
# Provide usage information if not arguments were supplied
if [[ "$#" -le 0 ]]; then
echo "Usage: $0 <executable> [<argument>...]" >&2
exit 1
fi
# Get the executable by removing the last slash and anything before it
X="${1##*/}"
# Get the directory by removing the executable name
D="${1%$X}"
# Check if the directory exists
if [[ -d "$D" ]]; then
# If it does, cd into it
cd "$D"
else
if [[ "$D" ]]; then
# Complain if a directory was specified, but does not exist
echo "Directory '$D' does not exist" >&2
exit 1
fi
fi
# Check if the executable is, well, executable
if [[ -x "$X" ]]; then
# Run the executable in its directory with the supplied arguments
exec ./"$X" "${#:2}"
else
# Complain if the executable is not a valid
echo "Executable '$X' does not exist in '$D'" >&2
exit 1
fi
Usage:
$ cdexec
Usage: /home/archon/bin/cdexec <executable> [<argument>...]
$ cdexec /bin/ls ls
ls
$ cdexec /bin/xxx/ls ls
Directory '/bin/xxx/' does not exist
$ cdexec /ls ls
Executable 'ls' does not exist in '/'
One source of such error messages under those conditions is a broken symlink.
However, you say the script works when run from the command line. I would also check to see whether the directory is a symlink that's doing something other than what you expect.
Does it work if you call it in your script with the full path instead of using cd?
#!/bin/bash
/path/to/a/folder/scriptname
What about when called that way from the command line?