Why is my link broken? Bash - bash

I am trying to link files in a while loop for my script but just the simple linking code itself creates a broken link.
The directory structure is this:
main/working/script.sh
main/working/dir
main/shared/default/some_files
My script has this code:
ln -s ../shared/default/* dir
This creates broken link. I can make the link not broken if I go inside the directory of main/working/dir and use ln -s ../../shared/default/* .

That is because you link to a relative path; Inside your script go to main/working/:
cd main/working/
ln -s ../shared/default/* dir
either use the absolute path:
ln -s /absolute/path/to/shared/default/* dir
you might even deduce the path where your script is located and use that path:
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
ln -s $DIR/../../shared/default/* dir
edit: bash cannot expand the * if you are not at the right directory, so you can work around that to temporarily change directories:
# go to dir to make correct relative links
cd dir
ln -s $DIR/../../shared/default/* ./
cd ..

Related

get folder name with find ... -name command in bash

Trying to get name of venv folder for activating it in bash script located inside the project. Because someone could use for venv another name like 'someones_env'
projectdir=$(cd ../../ && pwd)
echo "$(dirname "$projectdir")"
venvdir=$(find "$(dirname "$projectdir")" -name '*env')
echo "$(dirname "$venvdir")"
source "$(dirname "$venvdir")"/bin/activate
but $venvdir becomes the same as $projectdir instead of 'someones_env'
what am i doing wrong?
thanks
The directory of the *env folder is the project directory, that's why dirname "$venvdir" becomes the same as the project directory. Without dirname it should work.
Also, the directory of ../../ is ../../../, this might also be giving you some issues. If you are already in a directory, there's no need to use dirname. dirname calculates the parent directory.

high sierra bash shell script how to change directory

I work with high sierra and I have the following shell script
TOMCAT_PATH=/usr/local/Cellar/tomcat/9.0.12/
cd ./webapp/inventory/WEB-INF
rm -r -v classes
mkdir classes
cp -R ../../../classes ./classes
cd ..
jar -cvf inventory.war WEB-INF
cp inventory.war $TOMCAT_PATH/webapps
cd ../..
How can I execute the command
cd ./webapp/inventory/WEB-INF
After this cd the directory doesn't change
The current directory
/Users/carlotavina/Documents/carlota/irvine/javaenterprisedevelopment/curso6-webservices/week2/assignment/HW-2_Setup
In this directory I have subdirectory webapp/inventory. I want to move to this directory

Symbolic link source item can't be found

I'm trying to make an alias of a directory in a set of directories
for D in $(find * -maxdepth 0 -type d) ; do
ln -s location/to/directory/ $D/Test2 ;
done
It looks like the link is made correctly (I can see it in my finder window), but when I double click it, I get the error The operation can't be completed because the original item for "Test2" can't be found.
Why doesn't this work? Is there a way from a bash script to make a "normal" mac alias? I have opened up the permissions, as suggested here, without any luck.
Use the absolute source path while creating the link. That worked for me having the same issue.
You want to create a symbolic link called Test2 in each directory in the current directory, and each created link should point to location/to/directory.
for dir in */; do
ln -s 'location/to/directory' "$dir/Test2"
done
The slash after * ensures that we will only match directories in the current directory, or links to directories in the current directory.
If you're only interested in real directories an not symbolically linked directories, you may use
find . -type d -mindepth 1 -maxdepth 1 \
-exec ln -s 'location/to/directory' {}/Test2 ';'
Note that the link destination is relative to the location of the link, so if a directory does not contain location/to/directory, the link will be "dead".
You may solve this be specifying an absolute path for the links.
What are you attempting to do?
Think of a link as a cp command. Maybe that will help:
# Copies the 'svnadmin' command from /opt/svn/bin to /usr/local/bin
$ cp /opt/svn/bin/svnadmin /usr/local/bin
# Links the 'svnadmin' command from /opt/svn/bin to /usr/local/bin
$ ln -s /opt/svn/bin/svnadmin /usr/local/bin
Note that the ln and cp command have the same order of files.
In your command, you're linking whatever location/to/directory/ to $D/test2 over and over again.
Also, -maxdepth 0 won't be in the first level of the directory.
I use ln when I install new software, and the binary commands are in some other directory. Instead of building on $PATH to include all of these extra directories, I symbolically link them to /usr/local/bin:
$ cd /usr/share/apache-ant/bin
$ for file in *
> do
> [[ -f $file ]] || continue
> ln -s $PWD/$file /usr/local/bin/$file
> done
Note that the link simply copies the entire reference for the first file to the link. I want to make sure that this link works everywhere, so I prefix that $PWD in front of it. This way, my links look like this:
$ ls -l ant
lrwxr-xr-x 1 root wheel 29 Sep 3 2014 ant -> /usr/share/apache-ant/bin/ant

Retrieve parent directory of script

I'm working on an uninstaller script to delete the parent folder where the script is installed.
/usr/local/Myapplication/Uninstaller/uninstall.sh
So uninstall.sh has to do this:
rm- rf /usr/local/Myapplication
I can retrieve the folder where uninstall resides
SYMLINKS=$(readlink -f "$0")
UNINSTALL_PATH=$(dirname "$SYMLINKS")
But I'm still unsure of the pretty way to get the parent path.
I thought of using sed to demove the "Uninstaller" part of this path, but is there an elegant way to get the path to Myapplication folder to delete it?
Thank you
How about using dirname twice?
APP_ROOT="$(dirname "$(dirname "$(readlink -fm "$0")")")"
The quoting desaster is only necessary to guard against whitespace in paths. Otherwise it would be more pleasing to the eye:
APP_ROOT=$(dirname $(dirname $(readlink -fm $0)))
I put this answer as comment at 2018. But since I got a great feedback about the effectiveness of the solution, I will share it here as well :
# dir of script
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )";
# parent dir of that dir
PARENT_DIRECTORY="${DIR%/*}"
Just get the parent of the parent directory:
my_app_path=$(dirname $(dirname $(readlink -f "$0")))
If you need an absolute path, then you need cd. Otherwise you can just use $(dirname $0)/..
cd $(dirname $0)/..
path=$(pwd)
cd - # go back
the ultimate simple way of getting the parent directory path:
PARENT_DIRECTORY="${PWD%/*}"
Full path to parent dir of script, i.e. "/usr/local/bin/bla": export PARENT_OF_THIS_SCRIPT=$( cd $(dirname $0) ; pwd -P )
Just the most recent parent of script, i.e. "bla": export PARENT_DIR_OF_SCRIPT=$( cd $(dirname $0) ; pwd -P | xargs basename )
Why don't you simply add ../ at the end of the path?
As $0 can have suprising behavior, here is a solution using BASH_SOURCE[0]:
#/bin/bash
PARENT_DIR=$(dirname $(dirname $(readlink -f "${BASH_SOURCE[0]}")))

Prevent parent directories from being tarred

Basically I just want to tar all the files in a directory, but not get all the parent directories in the archive.
I've tried -C, but I guess I'm not using it right.
tar -cjf archive.tar.bz2 -C /var/some/log/path ./*
This results in tar trying to add all the files in the CWD. Using the full path as last argument doesn't prevent the dirs from being added.
Seems simple enough, but can't figure it out. Somehow tar does not tar ./* as being relative to -C, although it should change to that dir.
Help appreciated.
The parent directory (/var/some/log) is included, since /var/some/log/path/.. is included when you do ./*. Try just doing
tar -cjf archive.tar.bz2 -C /var/some/log/path .
Test run:
$ find tmp/some_files
tmp/some_files
tmp/some_files/dir1
tmp/some_files/dir1/dir1file
tmp/some_files/hello
tmp/some_files/world
tmp/some_files/dir2
tmp/some_files/dir2/dir2file
$ tar -cvjf archive.tar.bz2 -C tmp/some_files/ .
./
./dir1/
./dir1/dir1file
./hello
./world
./dir2/
./dir2/dir2file
$ cd tmp/unpacked
/tmp/unpacked$ mv /home/aioobe/archive.tar.bz2 .
/tmp/unpacked$ tar -xvjf archive.tar.bz2
./
./dir1/
./dir1/dir1file
./hello
./world
./dir2/
./dir2/dir2file
/tmp/unpacked$ ls
archive.tar.bz2 dir1 dir2 hello world
/tmp/unpacked$
There's a much easier way to do this:
cd down to the directory you wish to be top level, i.e...
cd /var/lib/mysql
Remove parent directories from your tar command
/var/lib/mysql/DATABASE_NAME becomes just DATABASE_NAME
More details can be found in this blog writeup.

Resources