correct way to get folder name from input - bash

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.

Related

Why is this bash script not changing path?

I wrote a basic script which changes the directory to a specific path and shows the list of folders, but my script shows the list of files of the current folder where my script lies instead of which I specify in script.
Here is my script:
#!/bin/bash
v1="$(ls -l | awk '/^-/{ print $NF }' | rev | cut -d "_" -f2 | rev)"
v2=/home/PS212-28695/logs/
cd $v2 && echo $v1
Does any one knows what I am doing wrong?
Your current script makes no sense really. v1 variable is NOT a command to execute as you expect, but due to $() syntax it is in fact output of ls -t at the moment of assignment and that's why you have files from current directory there as this is your working directory at that particular moment. So you should rather be doing ordinary
ls -t /home/PS212-28695/logs/
EDIT
it runs but what if i need to store the ls -t output to variable
Then this is same syntax you already had, but with proper arguments:
v1=$(ls -t /home/PS212-28695/logs/)
echo ${v1}
If for any reason you want to cd then you have to do that prior setting v1 for the same reason I explained above.

Bash: passing a variable to mv command option

--Bash 4.1.17 (running with Cygwin)
Hello, I am trying to pass the date into the --suffix option on the move (mv) command. I am able to pass in a simple string (like my name) but unable to pass in the date. If you run the script below you will see that the mv command with the suffix="$var" works but suffix="$now" does not.
#!/bin/bash
dir="your directory goes here"
now="$(date "+%m/%d/%y")"
var="_CARL!!!"
echo "$now"
echo "$var"
cd "$dir"
touch test.txt
# error if already exists
mkdir ./stack_question
touch ./stack_question/test.txt
mv -b --suffix="$var" test.txt ./stack_question/
The idea is that if test.txt already exists when trying to move the file, the file will have a suffix appended to it. So if you run this script with:
--suffix="$var"
you will see that the stack_question directory contains two files:
test.txt & test.txt_CARL!!!
But, if you run this script with:
--suffix="$now"
you will see that in the stack_question directory only contains:
test.txt
Any help on this would be greatly appreciated!
It is because you have embedded / in your date format try
now="$(date +%m_%d_%y)"

How-To get root directory of given path in bash?

My script:
#!/usr/bin/env bash
PATH=/home/user/example/foo/bar
mkdir -p /tmp/backup$PATH
And now I want to get first folder of "$PATH": /home/
cd /tmp/backup
rm -rf ./home/
cd - > /dev/null
How can I always detect the first folder like the example above? "dirname $PATH" just returns "/home/user/example/foo/".
Thanks in advance! :)
I've found a solution:
#/usr/bin/env bash
DIRECTORY="/home/user/example/foo/bar"
BASE_DIRECTORY=$(echo "$DIRECTORY" | cut -d "/" -f2)
echo "#$BASE_DIRECTORY#";
This returns always the first directory. In this example it would return following:
#home#
Thanks to #condorwasabi for his idea with awk! :)
You can try this awk command:
basedirectory=$(echo "$PATH" | awk -F "/" '{print $2}')
At this point basedirectory will be the string home
Then you write:
rm -rf ./"$basedirectory"/
If PATH always has an absolute form you can do tricks like
ROOT=${PATH#/} ROOT=/${ROOT%%/*}
Or
IFS=/ read -ra T <<< "$PATH"
ROOT=/${T[1]}
However I should also add to that that it's better to use other variables and not to use PATH as it would alter your search directories for binary files, unless you really intend to.
Also you can opt to convert your path to absolute form through readlink -f or readlink -m:
ABS=$(readlink -m "$PATH")
You can also refer to my function getabspath.
To get the first directory component of VAR:
echo ${VAR%${VAR#/*/}}
So, if VAR="/path/to/foo", this returns /path/.
Explanation:
${VAR#X} strips off the prefix X and returns the remainder. So if VAR=/path/to/foo, then /*/ matches the prefix /path/ and the expression returns the suffix to/foo.
${VAR%X} strips off the suffix X. By inserting the output of ${VAR#X}, it strips off the suffix and returns the prefix.
If you can guarantee that your paths are well formed this is a convenient method. It won't work well for some paths, such as //path/to/foo or path/to/foo, but you can handle such cases by breaking down the strings further.
To get the first firectory:
path=/home/user/example/foo/bar
mkdir -p "/tmp/backup$path"
cd /tmp/backup
arr=( */ )
echo "${arr[0]}"
PS: Never use PATH variable in your script as it will overrider default PATH and you script won't be able to execute many system utilities
EDIT: Probably this should work for you:
IFS=/ && set -- $path; echo "$2"
home
Pure bash:
DIR="/home/user/example/foo/bar"
[[ "$DIR" =~ ^[/][^/]+ ]] && printf "$BASH_REMATCH"
Easy to tweak the regex.
You can use dirname...
#/usr/bin/env bash
DIRECTORY="/home/user/example/foo/bar"
BASE_DIRECTORY=$(dirname "${DIRECTORY}")
echo "#$BASE_DIRECTORY#";
Outputs the following...
/home/user/example/foo

How to display or append several files in a terminal using shell script?

I would like to display several files one after another in a terminal, for instance, all the files of type .java in the current folder. Does anyone know how to do that by a line of shell? I guess probably we need to use cat and a variable...
Also, if possible, I would like to add the name of the files... For instance, the final layout in the terminal would be
p1.java
...
contents of p1.java
...
p2.java
...
contents of p2.java
...
Does anyone know how to do it? Thank you very much!
Could be as simple as:
$ cat *.java
If you want to display the filename before each listing, just use a loop:
$ for fn in *.java; do echo $fn; cat $fn; done
Just to enrich this answer a little bit: If you browse source code in your terminal regularly, you can get the content syntax highlighted as well via pygments. I use the following tiny function in my bashrc.
function pless() {
type -P pygmentize &> /dev/null || {
echo "pygmentize required but not installed. Aborting." >&2; return 1;
}
pygmentize "$#" | less -r
}
Here's an example screenshot:
Simple: cat file1 && cat file2
Or, alternatively: cat dir/*
Use this shell script.
#!/bin/sh
for filename in `find /path_to_file -maxdepth 1 -name "*.java"`
do
cat $filename
done
What is the use of find command is, you can specify 'maxdepth'. You can go into the deeper of the current folder and read .java files.

bash script list files from given user

I have a problem with this one.
It is constantly returning me, not a directory, but is certainly is
#!/usr/local/bin/bash
DIR=$1
if [ -d "$DIR" ]; then
ls -1Apl /home/$DIR | grep -v /\$
else
echo "not a directory"
fi
One more thing, I need a little hint. I have to list files from a given user in a given directory, where I get both the user and directory as parameters.
Just suggestions, please.
Are you in the /home directory when you run this? If not, you may want to change it to:
if [ -d "/home/$DIR" ]; then
to match the ls command. This is assuming you're running it with something like myscript pax to examine the /home/pax directory, which seems to be the case.
And if you want to only list those files in there owned by a specific user, you can use awk to only print those with column 3 set to the desired value ($usrnm), something like:
ls -1Apl /home/$DIR | grep -v /\$ | awk -v user=${usrnm} '$3==user{print}{}'
You're not testing for the existence of the same directory as you're trying to list - maybe you mean -d "/home/$DIR"? Or from your requirement, do you have two parameters?
user="$1"
dir="$2"
# and then examine "/home/$user/$dir"

Resources