I am doing bash script to check spelling on number of files.
I came across to problem of telling aspell to ignore some set of words that I allow to appear.
This is same as "Ignore All" in interactive mode. But that will not work as I would need to do that by hand.
How can I tell aspell to ignore given set of words. Is there any parameter that can do that.
I wish there was an option to pass file with those words.
Or might be out there a more efficient way for scripting spell checking in bash?
Easy: put your words in a Personal Dictionary: ~/.aspell.en.pws where the first line is
personal_ws-1.1 en 500
(500 is the number of words, doesn't need to be exact, aspell will fix it if you add words with aspell).
If you need the dictionary to be elsewhere, use options like these:
aspell --home-dir=/dir/to/dict --personal=dict-file.txt
This is written in a combination of shell and pseudocode. It does not seem like the most efficient way; parsing two arrays and checking the results takes up more memory and cycles than necessary.
function SpellCheckInit() {
for i in `seq 0 $(( ${#aname[#]} - 1 ))`; do
echo Parsing...
done
}
Dictionary=( "${dictionary[#]}" "Oxford English Dictionary" )
char=( "${words[#]}" "Text" )
echo Ignore?
read -a omt_wrds
SpellCheckInit()
words_left=${#Dictionary[#]}
until [ $words_left -lt 0]; do
if [ "$char" = "i"]; do
echo IGNORED
elif [ "$char" = "$Dictionary"]; do
echo CORRECT
else
for word in Dictionary
$word > $dictionary
done
fi
done
Related
I am trying to write a bash script that will tell whether two strings are of similar value. I have produced this bash script:
#!/bin/bash
value="java.lang.NullPointerException"
if [[ "java.lang.NullPointerException" = "$value" || "java.lang.NullPointerException" == "$value"* ]]; then
echo "Match"
fi
Basically what I want to achive, is that if two strings are of equal value or a very similar either side but with matching text in the middle then echo "Match".
I have tried a number of resources but can't get this example to work. I have taken a look at:
In bash, how can I check if a string begins with some value?
How to test that a variable starts with a string in bash?
https://ubuntuforums.org/showthread.php?t=1118003
Please note these values would eventually come from a text file and so the values will be in a form of variables. I have tried different approaches, but don't seem to get it working. I just want to get this if statement working. It works for matching text but not for values either side. Value could be "java.lang.NullPointerException: Unexpected" or "Unexpected java.lang.NullPointerException".
#!/bin/bash
value="java.lang.NullPointerException" #or java.lang.NullPointerException: Unexpected
if [[ $value == *"java.lang.NullPointerException"* ]];
then
echo "Match"
fi
A simple and portable (POSIX compliant) technique for wildcard matching is to use a case statement rather than if. For your example, this would look something like
#!/bin/sh
value="java.lang.NullPointerException"
case "$value" in
*java.lang.NullPointerException*) echo Match;;
esac
This is my first time using bash in college and it's being pretty hard now.
The exercise is:
Make a shell script which receives by parameter one word and a file list and adds the word in the beggining and ending of each file
So far what I've done is this:
#!bin/bash
word=$1;
i=2;
j=2;
for [ i -le $# ] in ls
do
for [ j -le $# ] in ls
do
if [ $i = $j ] then
$j=`word+$j+word`;
fi
done
done
and of course it doesn't work, but I really don't know why.
If anybody could help, it'd be great.
Sorry by any language mistake or convention in SO, I just arrived here. Thank you very much!
Since it's an exercise I'll give the answer in the way I would have wanted to learn about it:
Your script needs to take an arbitrary number of arguments - for example ./my_script.sh "my word" *.txt (note the space and quotes in the first parameter). There is a shell builtin command called shift which will remove the first argument from the argument list. The argument list is commonly referred to using "$#", but there is a handy shortcut syntax in Bash to loop over all arguments which avoids it entirely:
for argument
do
something with "$argument"
done
The exercise as originally stated says to add the string to the start and end of each file, not filename. There are plenty of examples of how to do that on this site and unix.SE.
You'll want to be careful about the difference between [ (aka. test) and [[.
Bash is not C - the ; command terminator is implicit at end of line (except of course in multi-line strings, here documents and the like).
I'm trying to compare values of two variables both containing strings-as-numbers. For example:
var1="5.4.7.1"
var2="6.2.4.5"
var3="1-4"
var4="1-5"
var5="2.3-3"
var6="2.3.4"
Sadly, I don't even know where to start... Any help will be appreciated!
What I meant is how would I go about comparing the value of $var5 to $var6 and determine with one of them is higher.
EDIT: Better description of the problem.
You can use [[ ${str1} < ${str2} ]] style test. This should work:
function max()
{
[[ "$1" < "$2" ]] && echo $2 || echo $1
}
max=$(max ${var5} ${var6})
echo "max=${max}."
It depends of the required portability of the solution. If you don't care about that and you use a deb based distribution, you can use the dpkg --compare-versions feature.
However, if you need to run your script on distros without dpkg I would use following approach.
The value you need to compare consist of first (the first element) and the rest (all others). The first is usually called the head and the rest - tail, but I deliberately use names first and rest, to not confuse with head(1) and tail(1) tools available on Unix systems.
In case first($var1) is not equal to first($var2) you just compares those firsts elements. If firsts are equal, just recursively run the compare function on rest($var1) and rest($var2). As a border case you need to decide what to do if values are like:
var1 = "2.3.4"
var2 = "2.3"
and in some step you will compare empty and non-empty first.
Hint for implementing first and rest functions:
foo="2.3-4.5"
echo ${foo%%[^0-9][0-9]*}
echo ${foo#[0-9]*[^0-9]}
If those are unclear to you, read man bash section titled Parameter Expansion. Searching the manual for ## string will show you the exact section immediately.
Also, make sure, you are comparing elements numerically not in lexical order. For example compare the result of following commands:
[[ 9 > 10 ]]; echo $?
[[ 9 -gt 10 ]]; echo $?
What is the best way to look inside a directory and determine whether its content are directories or files. Its a homework question.
My homework requires me to write a script that counts the number of directories, files, how many are executable, writeable, and readable.
Assuming you're talking about the bourne shell family, take a look at the -d, -x, -w... and I'm guessing -r tests. Look up how a for loop works in bash to see how to iterate over the files... the general idea is
for var in directory/*; do
#stuff with $var
done
But there are some particulars relating to spaces in filenames that can make this trickier.
Use the -X style operators:
[ -d "${item}" ] && echo "${item} is a directory"
See the bash man page (search for "CONDITIONAL EXPRESSIONS") to see the complete list.
Looping through contents of a directory and counting looks like this:
dirs=0
writeable=0
for item in /path/to/directory/*; do
[ -d "${item}" ] && dirs=$(( dirs + 1 )) # works in bash
[ -w "${item}" ] && writeable=`expr ${writeable} + 1` # works in bourne shell
# Other tests
done
echo "Found ${dirs} sub-directories"
echo "Found ${writeable} writeable files"
I'm not entirely new to programming, but I'm not exactly experienced. I want to write small shell script for practice.
Here's what I have so far:
#!/bin/sh
name=$0
links=$3
owner=$4
if [ $# -ne 1 ]
then
echo "Usage: $0 <directory>"
exit 1
fi
if [ ! -e $1 ]
then
echo "$1 not found"
exit 1
elif [ -d $1 ]
then
echo "Name\t\tLinks\t\tOwner\t\tDate"
echo "$name\t$links\t$owner\t$date"
exit 0
fi
Basically what I'm trying to do is have the script go through all of the files in a specified directory and then display the name of each file with the amount of links it has, its owner, and the date it was created. What would be the syntax for displaying the date of creation or at least the date of last modification of the file?
Another thing is, what is the syntax for creating a for loop? From what I understand I would have to write something like for $1 in $1 ($1 being all of the files in the directory the user typed in correct?) and then go through checking each file and displaying the information for each one. How would I start and end the for loop (what is the syntax for this?).
As you can see I'm not very familiar bourne shell programming. If you have any helpful websites or have a better way of approaching this please show me!
Syntax for a for loop:
for var in list
do
echo $var
done
for example:
for var in *
do
echo $var
done
What you might want to consider however is something like this:
ls -l | while read perms links owner group size date1 date2 time filename
do
echo $filename
done
which splits the output of ls -l into fields on-the-fly so you don't need to do any splitting yourself.
The field-splitting is controlled by the shell-variable IFS, which by default contains a space, tab and newline. If you change this in a shell script, remember to change it back. Thus by changing the value of IFS you can, for example, parse CSV files by setting this to a comma. this example reads three fields from a CSV and spits out the 2nd and 3rd only (it's effectively the shell equivalent of cut -d, -f2,3 inputfile.csv)
oldifs=$IFS
IFS=","
while read field1 field2 field3
do
echo $field2 $field3
done < inputfile.csv
IFS=oldifs
(note: you don't need to revert IFS, but I generally do to make sure that further text processing in a script isn't affected after I'm done with it).
Plenty of documentation out the on both for and while loops; just google for it :-)
$1 is the first positional parameter, so $3 is the third and $4 is the fourth. They have nothing to do with the directory (or its files) the script was started from. If your script was started using this, for example:
./script.sh apple banana cherry date elderberry
then the variable $1 would equal "apple" and so on. The special parameter $# is the count of positional parameters, which in this case would be five.
The name of the script is contained in $0 and $* and $# are arrays that contain all the positional parameters which behave differently depending on whether they appear in quotes.
You can refer to the positional parameters using a substring-style index:
${#:2:1}
would give "banana" using the example above. And:
${#: -1}
or
${#:$#}
would give the last ("elderberry"). Note that the space before the minus sign is required in this context.
You might want to look at Advanced Bash-Scripting Guide. It has a section that explains loops.
I suggest to use find with the option -printf "%P\t%n\t%u\t%t"
for x in "$#"; do
echo "$x"
done
The "$#" protects any whitespace in supplied file names. Obviously, do your real work in place of "echo $x", which isn't doing much. But $# is all the junk supplied on the command line to your script.
But also, your script bails out if $# is not equal to 1, but you're apparently fully expecting up to 4 arguments (hence the $4 you reference in the early part of your script).
assuming you have GNU find on your system
find /path -type f -printf "filename: %f | hardlinks: %n| owner: %u | time: %TH %Tb %TY\n"