Invalid option 3 for cat - linux

When I am trying to run the below Script it says invalid option 3 for cat..Whats the problem?
I am tried to use index file which specifies which file is ham and which is spam...to read the files and train spamfilter
#!bin/bash
DirBogoDict=$1
BogoFilter=/home/gunna/Downloads/bogofilter-1.2.4/src/bogofilter
x=0
for i in 'cat index | fgrep spam | head -300 | awk -F "/" '{print$2"/"$3}''
do
x=$((x+1)) ; echo $x
cat /home/gunna/Downloads/db-6.1.19.NC/build_unix/ceas08-1/$i| $BogoFilter -d $DirBogoDict -M -k 1024 -s
done
for i in 'cat index | fgrep ham | head -300 | awk -F "/" '{print$2"/"$3}''
do
x=$((x+1)) ; echo $x
cat /home/gunna/Downloads/db-6.1.19.NC/build_unix/ceas08-1/$i | $BogoFilter -d $DirBogoDict -M -k 1024 -n
done

This part
'cat index | fgrep spam | head -300 | awk -F "/" '{print$2"/"$3}''
needs to be in back-ticks, not single quotes
`cat index | fgrep spam | head -300 | awk -F "/" '{print$2"/"$3}'`
And you could probably simplify it a little with
for i in `fgrep spam index | head -300 | awk "/" '{print$2"/"$3}'`

Kdopen has explained the error you got , here is the improved code for similar for-loop function.
DirBogoDict=$1
BogoFilter=/home/gunna/Downloads/bogofilter-1.2.4/src/bogofilter
awk '/spam/&&++myctr<=300{print $2 FS $3}' FS="/" index |while read i
do
cat /home/gunna/Downloads/db-6.1.19.NC/build_unix/ceas08-1/"$i"| $BogoFilter -d ${DirBogoDict} -M -k 1024 -s
done
awk '/ham/&&++myctr<=300{print $2 FS $3}' FS="/" index |while read i
do
cat /home/gunna/Downloads/db-6.1.19.NC/build_unix/ceas08-1/"$i"| $BogoFilter -d ${DirBogoDict} -M -k 1024 -s
done

Also look at your file names , since cat is giving an error and an option is invalid. To demonstrate this, Let say you have a file a name -3error
executing the following command
cat -3error
will gave
cat: invalid option -- '3'
cat therefore is thinking the "-" is followed by one of its command line arguments. As a result you probably get an invalid option error.

Related

Unix - alter IP field an csv and output new file

Hoping for some input on this, as I'm struggling. I have a csv that contains an IP mask in which I want to get the network IP and broadcast IP.
So for instance I want the input field 1.0.0.0/24 to output 2 new field that contain the vaules: 1.0.0.0 in one and 1.0.0.255 in the other.
I have code to do this.
For broadcast:
for i in $(cat geoip.csv);do bcaddr=$(ipcalc -n -b $i);echo
${bcaddr#BROADCAST=};done
And for network:
for i in $(cat geoip.csv);do bcaddr=$(ipcalc -n -4 $i);echo
${bcaddr#BROADCAST=};done
Where do I go from here? How do I go about appending these 2 new fields to a new output file?
Thanks in advance!
see if this works on RHEL 5.x... do you want the output in csv with comma separator?
for i in $(cat csip.csv); do echo "$i $(ipcalc -n -b $i | grep -E "Address|Broadcast" | awk {'print ","$2'} | tr '\n' ' ')" ; done > new.csv
For your version of ipcalc, please try this:
for i in $(cat csip.csv); do echo "$i $(ipcalc -n -b $i | grep -E "NETWORK|BROADCAST" | awk -F= {'print ","$2'} | tr '\n' ' ')" ; done > new.csv
Why not using awk?
If you are using Linux (Not Unix):
for i in $(cat geoip.csv);do bcaddr=$(ipcalc -n -b $i); echo $bcaddr | egrep -o '([0-9]+\.){3}[0-9]+' ; done > ip.txt
Output:
1.0.0.255
1.0.0.0
If you want the output in a single line:
for i in $(cat geoip.csv);do bcaddr=$(ipcalc -n -b $i); echo $bcaddr | egrep -o '([0-9]+\.){3}[0-9]+' ORS=' ' ; done}' > ip.txt
Output:
1.0.0.255 1.0.0.0

How to get pipe string length?

This is a code that shows my all user names.
-q user | grep -A 0 -B 2 -e uid:\ 5'[0-9][0-9]' | grep ^name | cut -d " " -f2-
For example, the output is like...
usernameone
hello
whoami
Then, I hope that I want to check a length of all user names.
Like this output...
11 //usernameone
5 //hello
6 //whoami
How can I get a length of pipeline code?
Given some command cmd that produces the list of users, you can do this pretty easily with xargs:
$ cat x
usernameone
hello
whoami
$ cat x | xargs -L 1 sh -c 'printf "%s //%s\n" "$(echo -n "$1" | wc -c)" "$1"' '{}'
11 //usernameone
5 //hello
6 //whoami
To get a piped command might not be possible, so here's a one liner that uses a split and a while loop to accomplish this:
-q user | grep -A 0 -B 2 -e uid:\ 5'[0-9][0-9]' | grep ^name | cut -d " " -f2-|tr " " "\n"|while read user; do echo $(echo $user|wc -c) '//'$user;done|tr "\n" " ";echo
This should give you an output in the desired format. I used user as a file hence the cat
i=0;for token in $(cat user); do echo -n "${#token} //$token";echo;i=$((i+1));done;echo;

xargs -I % /path/ %

If torrent has a problem like deleted data on hard drive in id column it has number like "ID*".
I want to filter IDs of torrents in torrent list which have a symbol "*" at the end of id(LIKE ID* or 1*,2*,25*) and delete them from torrent list.
Full command is:
/usr/bin/transmission-remote 127.0.0.1:9091 --auth ts:ts -l | grep "*" | awk '{print $1}' \
| xargs -n 1 -I % /usr/bin/transmission-remote 127.0.0.1:9091 --auth ts:ts -t% -r
I expected result:
/usr/bin/transmission-remote 127.0.0.1:9091 --auth ts:ts -t ID* -r
But something went wrong.
Transmission said that:
127.0.0.1:9091/transmission/rpc/ responded: "success"
But torrent didn't delete from list.
How I can see the final result to compare with expected?
To get IDs :
transmission-remote -l | grep '*' | awk '{print $1}' | grep -o '[0-9]*'
The full command :
transmission-remote -l | grep '*' | awk '{print $1}' | grep -o '[0-9]*' | tr "\\n" "," | xargs -n 1 -I \% transmission-remote -t \% -r
Done and done (:
With the added improvement of using "tr" to join all torrent IDs and avoid running everything in a loop ( Transmission-RPC is extremely resource intensive to call repeatedly )

Command substitution as a variable in one-liner

I get the following error:
> echo "${$(qstat -a | grep kig):0:7}"
-bash: ${$(qstat -a | grep kig):0:7}: bad substitution
I'm trying to take the number before. of
> qstat -a | grep kig
1192530.perceus- kigumen lr_regul pbs.sh 27198 2 16 -- 24:00:00 R 00:32:23
and use it as an argument to qdel in openPBS so that I can delete all process that I started with my login kigumen
so ideally, this should work:
qdel ${$(qstat -a | grep kig):0:7}
so far, only this works:
str=$(qstat -a | grep kig); qdel "${str:0:7}"
but I want a clean one-liner without a temporary variable.
The shell substring construct you're using (:0:7) only works on variables, not command substitution. If you want to do this in a single operation, you'll need to trim the string as part of the pipeline, something like one of these:
echo "$(qstat -a | grep kig | sed 's/[.].*//')"
echo "$(qstat -a | awk -F. '/kig/ {print $1}')"
echo "$(qstat -a | awk '/kig/ {print substr($0, 1, 7)}')"
(Note that the first two print everything before the first ".", while the last prints the first 7 characters.) I don't know that any of them are particularly cleaner, but they do it without a temp variable...
qstat -u palle | cut -f 1 -d "." | xargs qdel
Kills all my jobs... normally I grep out the jobname(s) before cut'ing...
So I use a small script "idlist":
qstat -u palle | grep -E "*.in" | grep -E "$1" | cut -f 1 -d "." | xargs
To see all my "map_..." jobs:
idlist "map_*"
For killing all my "map_...." jobs:
idlist "map_*" | xargs qdel
yet another ways :
foreach m1 in $(qstat -a );do
if [[ $m1 =~ kig ]];then
m2=${m1%.kig}
echo "kig found $m2 "
break
fi
done

How do i append some text to pipe without temporary file

I am trying to get the max version number from a directory where i have several versions of one program
for example if output of ls is
something01_1.sh
something02_0.1.2.sh
something02_0.1.sh
something02_1.1.sh
something02_1.2.sh
something02_2.0.sh
something02_2.1.sh
something02_2.3.sh
something02_3.1.2.sh
something.sh
I am getting the max version number with the following -
ls somedir | grep some_prefix | cut -d '_' -f2 | sort -t '.' -k1 -r | head -n 1
Now if at the same time i want to check it with the version number which i already have in the system, whats the best way to do it...
in bash i got this working (if 2.5 is the current version)
(ls somedir | grep some_prefix | cut -d '_' -f2; echo 2.5) | sort -t '.' -k1 -r | head -n 1
is there any other correct way to do it?
EDIT: In the above example some_prefix is something02.
EDIT: Actual Problem here is
(ls smthing; echo more) | sort
is it the best way to merge output of two commands/program for piping into third.
I have found the solution. The best way it seems is using process substitution.
cat <(ls smthing) <(echo more) | sort
for my version example
cat <(ls somedir | grep some_prefix | cut -d '_' -f2) <(echo 2.5) | sort -t '.' -k1 -r | head -n 1
for the benefit of future readers, I recommend - please drop the lure of one-liner and use glob as chepner suggested.
Almost similar question is asked on superuser.
more info about process substitution.
Is the following code more suitable to what you're looking for:
#/bin/bash
highest_version=$(ls something* | sort -V | tail -1 | sed "s/something02_\|\.sh//g")
current_version=$(echo $0 | sed "s/something02_\|\.sh//g")
if [ $current_version > $highest_version ]; then
echo "Uh oh! Looks like we need to update!";
fi
You can try something like this :
#! /bin/bash
lastversion() { # prefix
local prefix="$1" a=0 b=0 c=0 r f vmax=0
for f in "$prefix"* ; do
test -f "$f" || continue
read a b c r <<< $(echo "${f#$prefix} 0 0 0" | tr -C '[0-9]' ' ')
v=$(((a*100+b)*100+c))
if ((v>vmax)); then vmax=$v; fi
done
echo $vmax
}
lastversion "something02"
It will print: 30102

Resources