BASH Dynamic Command Generation - bash

i'm stucked on this problem: i need a dynamic expression generation that has to be passed to ls command.
Here the code i tried:
op="ext"
fileName="MDL_test_"
fileExt=".csv"
if [[ $op == "noext" ]] ; then
searchExp="*$fileName*"
else
searchExp="*$fileName*$fileExt"
fi
ls "$("./files/"$searchExp)"
But when i execute the script this is what i get:
./ext_test.sh: line 15: ./files/MDL_test_30160410.csv.gz: Permission denied
ls: cannot access : No such file or directory
I think i'm doing something wrong, but i can't figure out it...

You just need to build the string up in pieces; most of the syntax is evaluated by the shell before passing the expanded result to ls.
if [[ $op == noext ]]; then
fileExt=
else
fileExt=.csv
fi
ls ./files/*"$fileName"*"$fileExt"

Related

Error using star as command line argument in script file

When I try to execute my script qwer.bash like this:
bash qwer.bash *whatever #whatever can really be anything
it will give back to me:
qwer.bash: line 5: [[: *whatever: syntax error: operand expected (error token is "*whatever")
here is my script:
#!/bin/bash
declare -a files
while [[ "$1" -ne "-p" ]]
do
echo "pwet"
shift
done
How can I avoid producing this error?
This is because the test $1 -ne ... generates an error when$1 is not an integer.
Try this:
while [[ "${#}" > 0 && "${1}" != "-p" ]]; do
echo "pwet"
shift
done
When shift is executed, ${#} decrements.
When "${#}" > 0 is false, the while loop ends. Note that && instructs the shell to not evaluate the second operand ("${1}" != "-p") when the first one is already false.
Though this is irrelevant in your case
Regarding
bash qwer.bash *whatever #whatever can really be anything
Case 1: If *whatever is meant to glob files :
bash qwer.bash ./*whatever
or
bash qwer.bash -- *whatever # here -- marks the end of options
or
./qwer.bash -- *whatever # you already have a shebang in your script.
This is to handle a case where you actually have a file named -file-with-dash in the current folder which may wrongly be taken as an option
Case 2: If *whatever is just a string:
bash qwer.bash \*whatever
or
bash qwer.bash "*whatever"

Bash - check for a string in file path

How can I check for a string in a file path in bash? I am trying:
if [[$(echo "${filePathVar}" | sed 's#//#:#g#') == *"File.java"* ]]
to replace all forward slashes with a colon (:) in the path. It's not working. Bash is seeing the file path string as a file path and throws the error "No such file or directory". The intention is for it to see the file path as a string.
Example: filePathVar could be
**/myloc/src/File.java
in which case the check should return true.
Please note that I am writing this script inside a Jenkins job as a build step.
Updates as of 12/15/15
The following returns Not found, which is wrong.
#!/bin/bash
sources="**/src/TESTS/A.java **/src/TESTS/B.java"
if [[ "${sources}" = ~B.java[^/]*$ ]];
then
echo "Found!!"
else
echo "Not Found!!"
fi
The following returns Found which also also wrong (removed the space around the comparator =).
#!/bin/bash
sources="**/src/TESTS/A.java **/src/TESTS/C.java"
if [[ "${sources}"=~B.java[^/]*$ ]];
then
echo "Found!!"
else
echo "Not Found!!"
fi
The comparison operation is clearly not working.
It is easier to use bash's builtin regex matching facility:
$ filePathVar=/myLoc/src/File.java
if [[ "$filePathVar" =~ File.java[^/]*$ ]]; then echo Match; else echo No Match; fi
Match
Inside [[...]], the operator =~ does regex matching. The regular expression File.java[^/]* matches any string that contains File.java optionally followed by anything except /.
It worked in a simpler way as below:
#!/bin/bash
sources="**/src/TESTS/A.java **/src/TESTS/B.java"
if [[ $sources == *"A.java"* ]]
then
echo "Found!!"
else
echo "Not Found!!"
fi

Error in shell script if condition [duplicate]

This question already has answers here:
Bash if statement syntax error [duplicate]
(3 answers)
Closed 9 years ago.
I didnt understand what he error here as iam new to shell scripting. Please help me
./bpr: line 8: syntax error near unexpected token `then'
./bpr: line 8: ` if[$(grep -o BPR $file | wc -l) == 1]; then '
You need to add spaces between your [ ], try this:
if [ $(grep -o BPR $file | wc -l) == 1 ]; then
You need a space around your condition:
if [ $(grep -o BPR $file | wc -l) == 1 ]; then
^ ^
1) If you are using bash, you can use the built-in [[ ..]] instead of test ([ ...]) command.
2) You can also avoid wc by using -c option of grep.
if [[ $(grep -c -o BPR $file) == 1 ]]; then
Aside from your syntax errors, you don't need wc either if you don't care that there may be multiple occurrances of BPR in the file:
if grep -o BPR "$file"; then
A couple of things:
You need spaces around [ and ].
You probably don't want to use [ and ].
The if statement runs the command you give it. If the command returns a zero, the then portion of the if statement is executed. If the command returns a non-zero, the else portion (if it exists) is executed.
Try this:
$ if ls some.file.name.that.does.not.exist
> then
> echo "Hey, the file exists!"
> else
> echo "Nope. File isn't there"
> fi
You'll get an output:
ls: some.file.name.that.does.not.exist: No such file or directory
Nope. File isn't there
That first statement, of course is the output of your ls command. The second one is the output from the if statement. The ls ran, but couldn't access that file (it doesn't exist) and returned e 1. That caused the else clause to execute.
Try this:
$ touch foo
$ if ls foo
> echo "Hey, the file exists!"
> else
> echo "Nope. File isn't there"
> fi
You'll get an output:
foo
Hey, the file exists!
Again the first line is your output from ls. Since the file exists, and is statable, ls returned a 0. This caused the if clause to execute, printing the second line.
What if I want to test whether or not a file exists?
You can use the test command:
$ if test -e foo
> then
> echo "Hey, the file exists!"
> else
> echo "Nope. File isn't there"
> fi
If the file foo exists, the test command returns a 0. That means the echo "Hey, the file exists!" will execute. If the file doesn't exist, test will return a 1, and the else clause will execute.
Now do this:
$ ls -il /bin/test /bin/[
10958 -rwxr-xr-x 2 root wheel 18576 May 28 22:27 /bin/[
10958 -rwxr-xr-x 2 root wheel 18576 May 28 22:27 /bin/test
That first number is the inode. If two matching files have the same inode, they are hard linked to each other. The [... ] are merely another name for the test command. The [ is an actual command. That's why you need spaces around it. You also see that if tests whether or not a command succeeds, and doesn't really do boolean checking (the exception is if you use double square brackets like [[ and ]] instead of [ and ]. These are built into the shell and not as builtin commands.)
What you probably want to do is:
if grep -q "BPR" "$file"
then
echo "'BPR' is in '$file'"
fi
The -q flag tells grep to shut its yap. The grep command will return a 0 if the pattern you give it is in the file, and a non-zero (exact value doesn't matter -- as long as it isn't 0) if it can't.
Note I don't need [ ... ] because I am using the output of the grep command to see if I should execute the if clause of that statement.
if you only need to know if the string matches without showing the actual match use
if grep -q 'anystring' file ; then

Bash script trouble interpretting input

I wrote a bash script that uploads a file on my home server. It gets activated from a folder action script using applescript. The setup is the folder on my desktop is called place_on_server. Its supposed to have an internal file structure exactly like the folder I want to write to: /var/www/media/
usage goes something like this:
if directory etc added to place_on_server: ./upload DIR etc
if directory of directory: etc/movies ./upload DIR etc movies //and so on
if file to place_on_server: ./upload F file.txt
if file in file in place_on_server ./upload F etc file.txt //and so on
for creating a directory its supposed to execute a command like:
ssh root#192.168.1.1<<EOF
cd /var/www/media/wherever
mkdir newdirectory
EOF
and for file placement:
rsync -rsh='ssh -p22' file root#192.168.1.1:/var/www/media/wherever
script:
#!/bin/bash
addr=$(ifconfig -a | ./test)
if ($# -le "1")
then
exit
elif ($1 -eq "DIR")
then
f1="ssh -b root#$addr<<EOF"
list = "cd /var/www/media\n"
if($# -eq "2")
then
list=list+"mkdir $2\nEOF\n"
else
num=2
i=$(($num))
while($num < $#)
do
i=$(($num))
list=list+"mkdir $i\n"
list=list+"cd $i\n"
$num=$num+1
done
fi
echo $list
elif ($1 -eq "F")
then
#list = "cd /var/www/media\n"
f2="rsync -rsh=\'ssh -p22\' "
f3 = "root#$addr:/var/www/media"
if($# -eq "2")
then
f2=f2+$2+" "+f3
else
num=3
i=$(($num))
while($num < $#)
do
i=$(($num))
f2=f2+"/"+$i
$num=$num+1
done
i=$(($num))
f2=f2+$i+" "+$f3
fi
echo $f2
fi
exit
output:
(prompt)$ ./upload2 F SO test.txt
./upload2: line 3: 3: command not found
./upload2: line 6: F: command not found
./upload2: line 25: F: command not found
So as you can see I'm having issues handling input. Its been awhile since I've done bash. And it was never extensive to begin with. Looking for a solution to my problem but also suggestions. Thanks in advance.
For comparisons, use [[ .. ]]. ( .. ) is for running commands in subshells
Don't use -eq for string comparisons, use =.
Don't use < for numerical comparisons, use -lt
To append values, f2="$f2$i $f3"
To add line feeds, use $'\n' outside of double quotes, or a literal linefeed inside of them.
You always need "$" on variables in strings to reference them, otherwise you get the literal string.
You can't use spaces around the = in assignments
You can't use $ before the variable name in assignments
To do arithmetics, use $((..)): result=$((var1+var2))
For indirect reference, such as getting $4 for n=4, use ${!n}
To prevent word splitting removing your line feeds, double quote variables such as in echo "$line"
Consider writing smaller programs and checking that they work before building out.
Here is how I would have written your script (slightly lacking in parameter checking):
#!/bin/bash
addr=$(ifconfig -a | ./test)
if [[ $1 = "DIR" ]]
then
shift
( IFS=/; echo ssh "root#$addr" mkdir -p "/var/www/media/$*"; )
elif [[ $1 = "F" ]]
then
shift
last=$#
file=${!last}
( IFS=/; echo rsync "$file" "root#$addr:/var/www/media/$*" )
else
echo "Unknown command '$1'"
fi
$* gives you all parameters separated by the first character in $IFS, and I used that to build the paths. Here's the output:
$ ./scriptname DIR a b c d
ssh root#somehost mkdir -p /var/www/media/a/b/c/d
$ ./scriptname F a b c d somefile.txt
rsync somefile.txt root#somehost:/var/www/media/a/b/c/d/somefile.txt
Remove the echos to actually execute.
The main problem with your script are the conditional statements, such as
if ($# -le "1")
Despite what this would do in other languages, in Bash this is essentially saying, execute the command line $# -le "1" in a subshell, and use its exit status as condition.
in your case, that expands to 3 -le "1", but the command 3 does not exist, which causes the error message
./upload2: line 3: 3: command not found
The closest valid syntax would be
if [ $# -le 1 ]
That is the main problem, there are other problems detailed and addressed in that other guy's post.
One last thing, when you're assigning value to a variable, e.g.
f3 = "root#$addr:/var/www/media"
don't leave space around the =. The statement above would be interpreted as "run command f3 with = and "root#$addr:/var/www/media" as arguments".

Why does my script report ls: not found

I have the following korn script:
#!/bin/ksh
TAPPDATADIR=/hp/qa02/App/IPHSLDI/Data
echo $TAPPDATADIR
if [[ls $TAPPDATADIR/zip_file_MD5_checksum*.txt | wc -l > 1]]
then
exit "asdf"
fi
When I attempt to run it I get:
/hp/qa02/App/IPHSLDI/Data
./iftest.ksh: line 7: [[ls: not found
Why isn't my if statement working?
I'm trying to see if there are multiple checksum files in the Data directory. If there are I want to exit the script.
There are several problems:
There shouldn't be any spaces around = in the assignment.
You need spaces around [[ and ]] in the if statement.
To substitute the result of a command into the test expression, you need to use backticks or $(...).
The parameter to exit should be a number, I think you just want to echo the string.
> performs string comparison, you have to use -gt to perform numeric comparison.
So the full script should be:
#!/bin/ksh
TAPPDATADIR=/hp/qa02/App/IPHSLDI/Data
echo $TAPPDATADIR
if [[ $(ls $TAPPDATADIR/zip_file_MD5_checksum*.txt | wc -l) -gt 1 ]]
then
echo "asdf"
fi

Resources