Is this an illegal syntax - bash

I am attempting to write a script that will generate a random number and then make a directory called that random number and copy in a text file. I have tried everything i could think of the assign the variable but each time i get
RANDOM: command not found
RANDOM: command not found
bash: //small.txt: No such file or directory
bash: //small.txt: No such file or directory
Below is my code
#!/bin/bash
one=$(RANDOM)
two=$(RANDOM)
mkdir -p $one
mkdir -p $two
echo “BIGGGGGONgrery54y457457yytewrterytyutytytyhtytryrtyrthrthtrhrtyhrthrhtrhrthrthrthrthE”| > $one/small.txt
echo “B”| > $two/small.txt
echo "finish -l test me "
done

It's not illegal syntax (it does mean something), it's just the wrong syntax for what you want. Instead of $(RANDOM) you want ${RANDOM} or even just $RANDOM.
When you use $() it's a command substitution, so bash is literally trying to execute a command named RANDOM, which is why you get command not found and nothing in your variables.
Your I/O redirection also looks wrong... to write to a file you should use:
echo "something" > file
Note that I removed the |.

FatalError covered the syntax problem, here's something related - how to generate a random number within a range (in this example, 1-100):
NUMBER=$(( ( $RANDOM % 100 ) + 1 ))
Also see: http://www.cyberciti.biz/faq/bash-shell-script-generating-random-numbers/ for other methods / information about random number generation in shell

Related

How to delete folders that fail a condition in bash script

I have a number of folders that are constantly and automatically generated. Some are garbage and need to be cleared out. Each folder produces a generations.txt which I want to count the important lines to determine whether or not the folder should be deleted. I'd like to have a bash script I can run every so often to clean things up.
Here's what I have. I can echo the command I want but I don't believe it outputs the integer to compare to 5. Any suggestions would really help me out. Please and thank you!
#!/bin/bash
SEARCHABLES="grep -Evc 'Value:' "
for d in */
do
PATH=$d'generations.txt'
COMMAND=$SEARCHABLES$PATH
if $COMMAND < 5
then
rm -rf $d
fi
done
You're not getting the output of the command, you need $(...) to execute a command and substitute its output.
To perform the arithmetic comparison, you have to put it inside ((...)).
#!/bin/bash
SEARCHABLES="grep -Evc 'Value:' "
for d in */
do
PATH="$d"'generations.txt'
COMMAND=$SEARCHABLES$PATH
if (( $($COMMAND) < 5 ))
then
rm -rf "$d"
fi
done
See BashFAQ/050 - I'm trying to put a command in a variable, but the complex cases always fail!
for a more detailed explanation.
In short, embedding a command in a variable is a faulty approach to the problem here because the single quotes in 'Value:' will be treated like literal data to search for. Syntax parsing happens before expansions, so you can't embed quotes in a variable like that. What you need is a function:
_count() {
grep -Evc 'Value:' "$1"
}
_count "$PATH"
Then compare the output of the function using an arithmetic expression:
occurrences=$( _count "$PATH" )
if (( occurrences < 5 )) ; then
...
fi

Exit shell script if file doesn't exist

Ive got a .sql job which creates files depending on certain criteria, it writes these with a prefix of TEMP_ as we then have an adaptor that picks up the files and we dont want them picked up before writing is complete.
I need to put a post job in place which renames these files, i have it set up with a number of other job but they all create the files each time they run. This job only creates the files sometimes it runs, depending on the data in the system.
I need to do a check if the file exists and then exit if no file exists.
Ive found a few examples but they all seem to fail, this is where i have got to which i thought was checking if no file, if no file then exit but it fails and displays:
"syntax error at line 16: `TEMP_SUBCON*.csv' unexpected"
This is what i have currently with line 16 being the first line - Above that is just comments:
if [[ ! -f $OUT_DIR -name TEMP_SUBCON*.csv ]] ; then
exit $?
fi
TEMP_DATA_FILE=$(find $OUT_DIR -name TEMP_SUBCON_QTY_output*.csv)
DATA_FILE=$(basename $TEMP_DATA_FILE | cut -c6-)
echo $TEMP_DATA_FILE
echo $DATA_FILE
## Rename the file name, remove the phrase TEMP_, so that EAI can pick the file ##
mv $TEMP_DATA_FILE $OUT_DIR/$DATA_FILE
Can you help guide what ive done incorrectly?
Thanks
If I understand it right, you want to find the files with TEMP_ prefix in your $OUT_DIR, and then if any rename them without the prefix. Then that should do the trick
for file in $OUT_DIR/TEMP_SUBCON_*.txt; do
if [[ -e $file ]]; then
mv $file $OUT_DIR/${file#*SUBCON_}
fi
done
exit
It will go through the directory finding each TEMP_ file and rename them without it. If there is none, it won't do anything.
That syntax is not valid for the [[ ... ]] test.
Why not use the result of the subsequent find command to check if there were any matching files in the specified directory instead, and quit if no files are returned (in other words, quit if the result variable is empty)?
Example:
TEMP_DATA_FILE=$(find $OUT_DIR -name "TEMP_SUBCON_QTY_output*.csv" )
if [[ -z ${TEMP_DATA_FILE:=""} ]] ; then
exit 1
fi
Note 1: you should quote the pattern argument for the find command as shown.
Note 2: it is useful to use set -u in your ksh scripts to cause ksh to abort if variables are unitialized when used (often the cause of errors) , instead of using a default value. However, if you use use set -u then in any test you should explicitly give your own default value. That is the reason for using ${TEMP_DATA_FILE:=""} instead of ${TEMP_DATA_FILE} - to support the often very useful set -u option. Even when you do not use set -u the ${TEMP_DATA_FILE:=""} inside tests makes it explicit what should happen instead of relying on implicit behaviour.
Note 3: you should use set -x when debugging and study every line of the output, it will show you exactly what commands ran with which arguments and what was the result. This helps you to learn how to code in ksh and similar shells.

Bash Script Loop

so I am trying to make a bash script loop that takes a users file name they want and the number of files they want and creates empty files. I made the script but I keep getting the error "./dog.sh: line 6: 0]: No such file or directory". I'm new to bash script and don't know what I'm doing wrong. Any help would be awesome thanks!
#!/bin/bash
echo "what file name do you want?"; read filename
echo "how many files do you want"; read filenumber
x=$filenumber
if [$x < 0]
then
touch $fiename$filenumber
x=$((x--))
fi
for x in $(seq "$filenumber"); do touch "$filename$x"; done
seq $filenumber produces a list of numbers from 1 to $filenumber. The for loop assigns x to each of these numbers in turn. The touch command is run for each value of x.
Alternative
In bash, if we can type the correct file number into the command line, the same thing can be accomplished without a for loop:
$ touch myfile{1..7}
$ ls
myfile1 myfile2 myfile3 myfile4 myfile5 myfile6 myfile7
{1..7} is called "brace expansion". Bash will expand the expression myfile{1..7} to the list of seven files that we want.
Brace expansion does have a limitation. It does not support shell variables. So, touch myfile{1..$filenumber} would not work. We have to enter the correct number in the braces directly.
Maybe it's a typo: $fiename instead of $filename
also, you might want some kind of loop like so:
x=1
while [ $x -le $filenumber ]; do
touch $filename$x
let x=x+1
done
#!/bin/bash
echo "what file name do you want?"; read filename
echo "how many files do you want"; read filenumber
x=$filenumber
while [ $x -gt 0 ]; do
touch $filename$x
x=$(( $x - 1))
done

Get output filename in Bash Script

I would like to get just the filename (with extension) of the output file I pass to my bash script:
a=$1
b=$(basename -- "$a")
echo $b #for debug
if [ "$b" == "test" ]; then
echo $b
fi
If i type in:
./test.sh /home/oscarchase/test.sh > /home/oscarchase/test.txt
I would like to get:
test.txt
in my output file but I get:
test.sh
How can I procede to parse this first argument to get the right name ?
Try this:
#!/bin/bash
output=$(readlink /proc/$$/fd/1)
echo "output is performed to \"$output\""
but please remember that this solution is system-dependent (particularly for Linux). I'm not sure that /proc filesystem has the same structure in e.g. FreeBSD and certainly this script won't work in bash for Windows.
Ahha, FreeBSD obsoleted procfs a while ago and now has a different facility called procstat. You may get an idea on how to extract the information you need from the following screenshot. I guess some awk-ing is required :)
Finding out the name of the file that is opened on file descriptor 1 (standard output) is not something you can do directly in bash; it depends on what operating system you are using. You can use lsof and awk to do this; it doesn't rely on the proc file system, and although the exact call may vary, this command worked for both Linux and Mac OS X, so it is at least somewhat portable.
output=$( lsof -p $$ -a -d 1 -F n | awk '/^n/ {print substr($1, 2)}' )
Some explanation:
-p $$ selects open files for the current process
-d 1 selects only file descriptor 1
-a is use to require both -p and -d apply (the default is to show all files that match either condition
-F n modifies the output so that you get one line per field, prefixed with an identifier character. With this, you'll get two lines: one beginning with p and indicating the process ID, and one beginning with `n indicating the file name of the file.
The awk command simply selects the line starting with n and outputs the first field minus the initial n.

How to let my program accept multiple variables and search the specified directory? Bash Script

#!/bin/bash
echo input directory 1
read dir1
dir1a="$dir1"
echo input directory 2
read dir2
dir2a="$dir2"
pathIs="/$dir1/$dir2"
cd $pathIs
echo $pathIs
echo input file name
read file
find . -iname "$file" -print
The above script works fine so long i know how many directories and subdirectories i am going to search (2 in the above example).
My questions:
1. I would like to modify it to work to any number of subdirectories (example 3 or 4)?
2. Even I use for loop to enter multiple directories, i get the problem how to tell the
pathIs variable, how many directories i have entered?
#!/bin/bash
echo directory name
read num
for i in $num
do
echo input directory 1
read dir
done
pathIs="/$dir1/$dir2"
cd $pathIs
echo input file name
read file
find . -iname "$file" -print
There are two options.
Ask the user in advance how many entries will be provided, then read that many times
Let the user terminate their entries, perhaps by giving an empty entry
To do the second option, you could use a general pattern in most programming languages - a "read ahead, read while" loop.
read x
while [ $x ]; do
echo "Do something with $x"
read x
done
echo "DONE"
So we read x once. Then we go into a while loop, which checks the variable, does something with it, then reads into it again, and keeps going until a terminating condition is encountered.
In the example above, if [ $x ] evaluates to false (an empty string), then the loop exits. Instead of echo "Do something with $x", you'll want to append the string to the pathIs variable.
One other thing -- most useful shell scripts don't read inputs of that kind from stdin. Eventually you'll want to process parameters given at the command line instead.
You can also read input arguments from the command line like this:
for i in {1..$#}
do
variable[i]=$1
shift
done
The loop goes through all command line arguments, reading them into the "variable" array

Resources