Bash cd .. returns nothing - bash

I have a Bash script:
src="/home/xubuntu/Documents"
mkdir -p "$src/folder1"
src="$src/folder1"
# Do something
printf "SRC IS: $src\n"
src=`cd ..` # RETURN TO PARENT DIRECTORY
printf "SRC IS: $src\n"
Basically I want to create a new folder, then do something inside the folder and after that's done I want to return to the parent directory Documents. For some reason however, src=`cd ..` returns nothing.
SRC IS: /home/xubuntu/Documents
SRC IS:
Any ideas why?

You can access to the parent :
src=$(cd ..&&pwd)
Much better and without using cd:
src=${src%/*} # src is the parent directory

cd is just to change directory, not to display it; that is done with pwd; i.e.
cd ..
src=`pwd`
#or slightly faster
src=$PWD

what is happening is you are assigning the output from the command "cd .." to src
which (as you can see when you do it on the command line) is nothing. Use readlink -f to accomplish what you need.
What you want to do instead is this:
src="/home/xubuntu/Documents"
mkdir -p "$src/folder1"
src="$src/folder1"
# Do something
printf "SRC IS: $src\n"
src=`readlink -f $src/..` # RETURN TO PARENT DIRECTORY
printf "SRC IS: $src\n"
i assume thats what you wanted to do, return the the src it's parent folder.

Related

Unix Bash Script Create Directory parent and child method

I'm trying to create directory using if condition statement, while running script i am not able to find any expected result from the script, but when i am running manually only mkdir command alone its creating as we expected; here the sample code.
#!/bin/bash
dir_path=/tmp/opt/app/software/{A,B,C,D}
if [[ -d $dir_path ]]; then
mkdir -p /tmp/opt/app/software/{A,B,C,D}
fi
can you please advise, how we can create this..
dir_path is a "list" of directory paths due to the {} parameter expansion. If you write this out:
dir_path=/tmp/opt/app/software/A /tmp/opt/app/software/B /tmp/opt/app/software/C /tmp/opt/app/software/D
This is what's being used in the test of the if statement.
Either you want to iterate over the list of sub directories, or just pass them to mkdir. mkdir simply won't create the directory if it already exists.
Your mkdir command actually expands out to:
mkdir -p /tmp/opt/app/software/A /tmp/opt/app/software/B /tmp/opt/app/software/C /tmp/opt/app/software/D
If you want to itterate and still do a check (which while needless in this example can still be useful other times.)
# Declare the variable `dirs` to be an array and use
# parameter expansion to populate it
declare -a dirs=(/tmp/opt/app/software/{A,B,C,D});
# Iterate over the array of directory names
for dir in ${dirs[#]}; do
if [ ! -d "$dir" ]; then
# The directory does not exsist
mkdir -p "$dir"; # Make the directory
fi
done

Is it possible to CD into a file?

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.

Run a command to make a directory through bash

I am creating a command that when executed will automatically make a folder on my desired location and put some files in it so I can get started quickly but for some reason I am not being able to create a directory. The goal is to pass a variable for the name of the directory to be created.
I have used mkdir and then pass the path and file name no errors are shown but the directory is not created. I even used eval.
#!/bin/bash
echo File name:
read file
cd ~/Desktop
mkdir $file
I expect the directory to be created and shown.
Use quotes:
mkdir "$file"
Example of what might happen if you do not use quotes:
file="hello world"
mkdir $file
This creates 2 directories "hello" and "world", and not the expected directory "hello world".

correct way to get folder name from input

I wrote one script and I have problem to get name of folder from stdin
here is my problem;
myfunc:
#!/bin/bash
audio=$1
mkdir -p ${audio}_rnn
...
rest of code
...
I call my function:
$./myfunc testdir
in this way I have my expected output, that means I have another dir with name testdir_rnn in the current directory.
But when I call my function like this:
$./myfunc testdir/
I have problem; it create _rnn folder inside testdir folder becaues:
echo ${audio}_rnn in this case is testdir/_rnn
What is the correct way to get folder name from input?
You just need to trim the '/'. Please use ${1%/} in your code as below:
audio=${1%/}
mkdir -p ${audio}_rnn
...
rest of code
...
you could remove the last "/" with sed using regular expressions:
#!/bin/bash
echo 'Dir/test/' | sed 's/\/$//'
Output: Dir/test
Assuming that directory will be passed without the upper levels.
You can use somthing like cut
#!/bin/bash
my_dir=$(echo $1 | cut -d "/" -f1)
mkdir -p "${my_dir}_rnn"
....
rest of the code
....
Now run the script with
./my_script.sh test_dir or ./my_script.sh test_dir/ (both will work).
Add a period (.) before the variable, can fix this issue as per your need.
#!/bin/bash
audio=$1
mkdir -p .${audio}_rnn
But for this to create a dir _rnn, you must already have testdir/ already in place.

Bash go to level 1 subdir if inside parentsubdir

Okay,
I would like to do the following in the shell.
If I am in a subdir like css which is inside a subdir like mypage (e.g. projects/mypage/htdocs/css) I would like to go into the root dir of the project, which is mypage. I would like to write this as a function to us as a command. The only "fixed" value is projects.
So basically if I am within any subdir of projects in the shell and I type the command goroot (or whatever) I want the function to check if it is in fact inside a subdir of projects and if so, go to the current subdir.
E.g.
~/projects/mypage/htdocs/css › goroot [hit return]
~/projects/mypage > [jumped to here]
Is this at all possible and if so how could I achieve this?
Assuming I am understanding correctly, this should work:
goroot() { cd $(sed -r 's#(~/projects/[^/]*)/.*#\1#' <<< $PWD); }
This sed command effectively strips off everything after ~/projects/SOMETHING and then changes to that directory. If you're not in ~/projects/ then it will leave you in the current directory.
Note: this assumes that $PWD uses the ~ to denote home, if it is something like /home/user/ then amend the sed command appropriately.
projroot=/home/user/projects
goroot() {
# Strip off project root prefix.
local m=${d#$projroot/}
if [ "$m" = "$d" ]; then
echo "Not in ~/projects"
return
fi
# Strip off project directory.
local suf=${m#*/}
if [ "$suf" = "$m" ]; then
echo "Already in project root."
return
fi
# cd to concatenation of project root, and project directory (stripped of sub-project path).
cd "$projroot/${m%/$suf}"
}

Resources