I have a bash script that does except some actions the following:
mv "$currentDir" "$currentDir#backup"
mv "$tempBuild" "$currentDir"
I run my script by doing two steps:
cd /path/to/project
./my_script.sh
I expected that $currentDir should always be equated to /path/to/project.
But when I run it second time by adding the 3rd step ./my_script.sh the current directory value becomes /path/to/project#backup.
What am I doing wrong, is it possible to improve the script for doing that stuff or should I change an approach?
Also I'm getting the current directory by this way:
currentScriptAbsolutePath=$(cd `dirname "${BASH_SOURCE[0]}"` && pwd)/`basename "${BASH_SOURCE[0]}"`
currentDirAbsolutePath=$(dirname $currentScriptAbsolutePath)
Any help is appreciated and thank you in advance.
In my toolbox I have this to get the script path and the caller path.
This can help you
# Set path
CALLER_PWD=$(pwd)
case "$0" in
*/*)
SCRIPT_PWD=`dirname "$0"`
;;
*)
SCRIPT_PWD=`/bin/which "$0" | head -1`
SCRIPT_PWD=`dirname "$SCRIPT_PWD"`
;;
esac
cd "$SCRIPT_PWD"
SCRIPT_PWD=$(pwd)
cd "$CALLER_PWD"
Related
I find a list of files that I need to cd to (obviously to the parent directory).
If I do cd ./src/components/10-atoms/fieldset/package.json I get the error cd: not a directory:, which makes sense.
But isn't there a way to allow for that? Because manipulating the path-string is pretty cumbersome and to me that would make total sense to have an option for that, since cd is a directory function and it would be cool that if the path would not end up in a file, it would recursively jump higher and find the "first dir" from the given path.
So cd ./src/components/10-atoms/fieldset/package.json would put me into ./src/components/10-atoms/fieldset/ without going on my nerves, telling me that I have chosen a file rather than a dir.
You could write a shell function to do it.
cd() {
local args=() arg
for arg in "$#"; do
if [[ $arg != -* && -e $arg && ! -d $arg ]]; then
args+=("$(dirname "$arg")")
else
args+=("$arg")
fi
done
builtin cd ${args[0]+"${args[#]}"}
}
Put it in your ~/.bashrc if you want it to be the default behavior. It won't be inherited by shell scripts or other programs so they won't be affected.
It modifies cd's arguments, replacing any file names with the parent directory. Options with a leading dash are left alone. command cd calls the underlying cd builtin so we don't get trapped in a recursive loop.
(What is this unholy beast: ${args[0]+"${args[#]}"}? It's like "${args[#]}", which expands the array of arguments, but it avoids triggering a bash bug with empty arrays on the off chance that your bash version is 4.0-4.3 and you have set -u enabled.)
This function should do what you need:
cdd() { test -d "$1" && cd "$1" || cd $(dirname "$1") ; }
If its first argument "$1" is a directory, just cd into it,
otherwise cd into the directory containing it.
This function should be improved to take into account special files such as devices or symbolic links.
You can if you enter a bit longer line (or create dedicated shell script)
cd $(dirname ./src/components/10-atoms/fieldset/package.json)
If you add it in script it can be :
cd $(dirname $1)
but you need to execute it on this way:
. script_name ./src/components/10-atoms/fieldset/package.json
You can put this function in your ~/.bashrc:
function ccd() {
TP=$1 # destination you're trying to reach
while [ ! -d $TP ]; do # if $TP is not a directory:
TP=$(dirname $TP) # remove the last part from the path
done # you finally got a directory
cd $TP # and jump into it
}
Usage: ccd /etc/postfix/strangedir/anotherdir/file.txt will get you to /etc/postfix.
I'm a new for Mac developing.
I try to create project.sh file and run it via Terminal
See mac.zip for more details.
The main class (com.myclass.MyClass) is in "main.jar" that requires lib1.jar, lib2.jar, and sublib1.jar
The "CLASSPATH" property in "project.sh" is created via script, it cannot be changed in project.sh
The value is always in relative path format such as "../../lib/lib1.jar"
When I try to run it from "mac/project" directory that contains main.jar and project.sh via Mac Terminal
It work fine as following
Gui-iMac:project gui$ ./project.sh
AClass
BClass
CClass
However, when I try to run project.sh from other directory, it failed.
For example: run from desktop directory:
Gui-iMac:desktop gui$ "/Users/gui/Desktop/GUI/Mac/project/project.sh"
Error: Could not find or load main class com.myclass.MyClass
How can I run project.sh from other directory?
Please help me to solve this problem.
Thanks in advance.
earist
I don't know if this is the answer that you are looking for but to run a .sh script from another directory you can use
$sh /Users/gui/Desktop/GUI/Mac/project/project.sh
Now, I find the solution for this problem.
using
cd "$directoryName" && exec "$myCommand"
as following:
#!/bin/bash
BASE=$(dirname "$0")
ARGS=""
if [ $# -gt 1 ]; then
while [ $# -ge 1 ]; do
case "$1" in
-[a-z]*) ARGS="$ARGS $1" ;;
*) ARGS="$ARGS \"$1\"" ;;
esac
shift
done
fi
CLASSPATH=.:../lib/lib1.jar:../lib/lib2.jar:./lib/sublib1.jar:./main.jar
JAVA_COMMAND=java
VM_OPTIONS="-Xmx800M"
EXEC_COMMAND="cd \"$BASE\" && exec $JAVA_COMMAND $VM_OPTIONS -cp $CLASSPATH com.myclass.MyClass $ARGS"
eval $EXEC_COMMAND
I'm not a pro in shell scripting, thats why I ask here :).
Let's say I got a folder. I need a script that monitors that folder for new files (no prefix name of files is given). When a new file gets copied into that folder, another script should start. Has the second script processed the file successfully the file should be deleted.
I hope you can give me some ideas on how to achieve such script :)
Thank you very much in advance.
Thomas
Try this:
watcher.sh:
#!/bin/bash
if [ -z $1 ];
then
echo "You need to specify a dir as argument."
echo "Usage:"
echo "$0 <dir>"
exit 1
fi
while true;
do
for a in $(ls -1 $1/* 2>/dev/null);
do
otherscript $a && rm $a #calls otherscript with the file a as argument and removes it if otherscript returned something non-zero
done
sleep 2s
done
Don't forget to make it executable
chmod +x ./watcher.sh
call it with:
./watcher.sh <dirname>
try inotify(http://man7.org/linux/man-pages/man7/inotify.7.html)
or you may need to install inotify-tools (http://www.ibm.com/developerworks/linux/library/l-ubuntu-inotify/) to use it by shell.
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
}
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?