ack command didn't return output from current directory in bash script - bash

(edited)
Let say i have some directory structure like this:
lv1_directory
| file_contain_word_something.txt
| lv2_directory
so now i'm at lv2_directory and i have a code like this:
#!/bin/bash
findfile=$(ack -n 'something' . | wc -l)
cd ..
ls
echo $findfile
when i run the script it give me
lv2_directory file_contain_word_something.txt
0
but if i didn't assign it to variable it work like charm
#!/bin/bash
cd ..
ls
ack -n 'something' | wl -l
it give me
lv2_directory file_contain_word_something.txt
1
so i have to change it to this to work
#!/bin/bash
findfile=$(ack -n 'something' .. | wc -l)
cd ..
ls
echo $findfile
it give me the result i want
lv2_directory file_contain_word_something.txt
1
How can i use the first script and give me the result i want?

I think the problem here is:
You are currently inside lv2_directory which DOES NOT HAVE any file which matches the string 'something'. So when you fire ack from this dir itself, you get 0 for number of lines. Then you do cd...
#!/bin/bash
findfile=$(ack -n 'something' . | wc -l)
cd ..
ls
echo $findfile
Now, in your next snippet:
#!/bin/bash
cd ..
ls
ack -n 'something' | wl -l
You are first doing cd, so you are into lv1_directory, which has the file file_contain_word_something.txt. Then you fire your ack. Now it finds something in the txt file and hence, gives you 1 as the output(assuming there's only 1 matching line).

Like you wrote your script, it will never list (ls instruction), and count (wc instruction) in the same directory, so you have no result guarantee.
In addition, according to the directory in which you will launch the script, it may not work at all.
May you consider managing path at beginning of your script (and don't modify it between your instructions)?
Do you exactly know where is it on the system?
An alternative, may be to create an environment variable (for instance in your ~/.bash_profile file), and to use it at beginning of your script, ensuring it'll always be run in the good directory.

after some experiment i can achieve the result i want using function
#!/bin/bash
function findfile(){
ack -n 'something' | wc -l
}
cd ..
findfile
and its gonna give you 1
thank you for answering my question

Related

Same script is giving result zero on cron where manually getting correct result

#!/bin/bash
cd /ad/bd/cd/dd/ed/zd
count=$(find . -type f|cut -d "/" -f3|wc -l)
echo $count >> /ad/bd/cd/abc.log
#exit
Manually it is giving correct value. i.e 230
ad/bd/script
when above cron running it is giving zero i.e 0
Try specifying absolute path of the directory in find where you want to look for files
count=$(find "/ad/bd/cd/dd/ed/zd" -type f | cut -d "/" -f3 | wc -l)
In general, cron runs your commands in your home directory. If you want to run your script from a specific directory, start that shell snippet by a command to change the directory like this:
0 10 * * * cd /some/dir && /path/to/script args
Please note that, the use of && over ; doesn’t make any difference, but if the cd command fails (for instance, because of the target directory doesn’t exist) with && your script is not executed, whereas with ; it's executed (but in an unintended directory).

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.

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.

Can I use a variable in a file path in bash? If so, how?

I'm trying to write a small shell script to find the most recently-added file in a directory and then move that file elsewhere. If I use:
ls -t ~/directory | head -1
and then store this in the variable VARIABLE_NAME, why can't I then then move this to ~/otherdirectory via:
mv ~/directory/$VARIABLE_NAME ~/otherdirectory
I've searched around here and Googled, but there doesn't seem to be any information on using variables in file paths? Is there a better way to do this?
Edit: Here's the portion of the script:
ls -t ~/downloads | head -1
read diags
mv ~/downloads/$diags ~/desktop/testfolder
You can do the following in your script:
diags=$(ls -t ~/downloads | head -1)
mv ~/downloads/"$diags" ~/desktop/testfolder
In this case, diags is assigned the value of ls -t ~/downloads | head -1, which can be called on by mv.
The following commands
ls -t ~/downloads | head -1
read diags
are probably not what you intend: the read command does not receive its input from the command before. Instead, it waits for input from stdin, which is why you believe the script to 'hang'. Maybe you wanted to do the following (at least this was my first erroneous attempt at providing a better solution):
ls -t ~/downloads | head -1 | read diags
However, this will (as mentioned by alvits) also not work, because each element of the pipe runs as a separate command: The variable diags therefore is not part of the parent shell, but of a subprocess.
The proper solution therefore is:
diags=$(ls -t ~/downloads | head -1)
There are, however, further possible problems, which would make the subsequent mv command fail:
The directory might be empty.
The file name might contain spaces, newlines etc.

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