Bash, grep sentence from file - bash

I have made a simple answering machine in bash. Basically if you greet it, it will greet you back but now I have a problem with sentence analyzing.
If the sentence ($#) is more than one word, it fails.
if [[ "$#" = $(grep -Fx "$#" 'vocabulary/greeting') ]]
then
speak greeting
elif [[ "$#" = $(grep -Fx "$#" 'vocabulary/appreciative') ]]
The output:
> hello
Sam: Hi!
> how are you
grep: are: No such file or directory
grep: you: No such file or directory
grep: are: No such file or directory
grep: you: No such file or directory
grep: are: No such file or directory
grep: you: No such file or directory
grep: are: No such file or directory
grep: you: No such file or directory
grep: are: No such file or directory
grep: you: No such file or directory
Sam: I don't understand.
>
How do I fix this?
How can I catch possible errors like these in the future?

Use "$*" instead of "$#".
if [[ "$*" = "$(grep -Fx "$*" 'vocabulary/greeting')" ]]
"$*" is a string representation of the arguments, while "$#" is an array.

Related

unable to get the complete list of file matching the regular expression in shell script

I have a directory with list of files abc_1.txt abc_2.txt.
I am have to parse the file name and do some processing over the file
#shellscript /tmp/log*
file_list=`ls $1`
for file_name in $file_list
do
# need to do some processing over the file name
echo $file_name
done
the script is not giving the proper output i.e script is not giving matching wildcard file name for the ls cmd.
the usage of the above script is shellscript /tmp/log*
Bash expands shellscript /tmp/log/abc* to a list of files names as input to your script. ls is not needed. Just iterate over the input. Try it like this
for f in $*
do
echo "Processing $f"
# do something on $f
done
http://www.cyberciti.biz/faq/bash-loop-over-file/ even gives you some more examples.
When you want filenames without the dir you can use
if [ ! -d "$*" ]; then
echo "Usage: $0 dirname"
exit 1
fi
cd "$*"
find . -type f | cut -c3- | while read file_name; do
echo "Found ${file_name}"
done
Just remove the wildcard character "*" since it matches all the files in the given path. Removing it will just pass the directory path and your script will print each file

check multiple files existing in a directory or not

I am new to UNIX, please help.
I have a file which has many lines, each line is a filename.
Now I want to check if each file exists in another directory with some prefixes.
For example, my text file content is
abc.def.ghi.jkl
mno.pqr.stu.vwx
I want to test if each file exists in a directory, like
cd <search directory>
ls -ltr *abc.def.ghi.jkl*
If above result is false then throw an error.
Note: The file content is DYNAMIC and I am generating this file through another script.
Assuming your file is
$ cat myList
abc.def.ghi.jkl
mno.pqr.stu.vwx
A quick solution is
cat myList | xargs ls -ltr
If files are not found, the output of ls will complain to stdout with
ls: xxx: No such file or directory
IHTH
This is the expected Answer
`ls -l > temp.cat
for i in $(cat temp.txt)
do
ls -l *$i*
if [[ $? -eq 0 ]]
then
echo " File found"
else
echo " File not found for $i"
fi
done
rm -f temp.txt`
`

remove substring from filename

I have files with name of the form "NAME-xxxxxx.tedx" and I want to remove the "-xxxxxx" part. The x are all digits.
The regex "\-[0-9]{1,6}" matches the substring, but I have no idea how to remove it from the filename.
Any idea how I can do that in the shell?
If you have the perl version of the rename command installed, you could try:
rename 's/-[0-9]+//' *.tedx
Demo:
[me#home]$ ls
hello-123.tedx world-23456.tedx
[me#home]$ rename 's/-[0-9]+//' *.tedx
[me#home]$ ls
hello.tedx world.tedx
This command is smart enough to not rename files if it means overwriting an existing file:
[me#home]$ ls
hello-123.tedx world-123.tedx world-23456.tedx
[me#home]$ rename 's/-[0-9]+//' *.tedx
world-23456.tedx not renamed: world.tedx already exists
[me#home]$ ls
hello.tedx world-23456.tedx world.tedx
echo NAME-12345.tedx | sed "s/-[0-9]*//g"
will give NAME.tedx. So you can use a loop and move the files using mv command:
for file in *.tedx; do
newfile=$(echo "$file" | sed "s/-[0-9]*//g")
mv "$file" $newfile
done
If you want to use just the shell
shopt -s extglob
for f in *-+([0-9]]).tedx; do
newname=${f%-*}.tedx # strip off the dash and all following chars
[[ -f $newname ]] || mv "$f" "$newname"
done

Problem Listing files in bash with spaces in directory path

When entered directory into the command line, this:
ls -d -1 "/Volumes/Development/My Project/Project"/**/* | grep \.png$
Prints a list of all the file ending in .png.
However when I try and create a script:
#! /bin/bash
clear ;
# Tempoary dir for processing
mkdir /tmp/ScriptOutput/ ;
wdir="/Volumes/Development/My Project/Project" ;
echo "Working Dir: $wdir" ;
# Get every .PNG file in the project
for image in `ls -d -1 "$wdir"/**/* | grep \.png$`; do
...
done
I get the error:
cp: /Volumes/Development/My: No such file or directory
The space is causing an issue, but I don't know why?
Another option is to change IFS:
OLDIFS="$IFS" # save it
IFS="" # don't split on any white space
for file in `ls -R . | grep png`
do
echo "$file"
done
IFS=$OLDIFS # restore IFS
Read more about IFS in man bash.
Use more quotes and don't parse ls output.
for image in "$wdir"/**/*.png; do
If you fine with using while read and subprocess created by pipe, you can:
find . -name '*.png' | while read FILE
do
echo "the File is [$FILE]"
done
you can try, [[:space:]] in place of space
wdir="/Volumes/Development/My[[:space:]]Project/Project"
or execute command to convert single space
wdir=`echo "$wdir" | sed 's/[[:space:]]/\[[:space:]]/g'`

Trying to cat files - unrecognized wildcard

I am trying to create a file that contains all of the code of an app. I have created a file called catlist.txt so that the files are added in the order I need them.
A snippet of my catlist.txt:
app/controllers/application_controller.rb
app/views/layouts/*
app/models/account.rb
app/controllers/accounts_controller.rb
app/views/accounts/*
When I run the command the files that are explicitly listed get added but the wildcard files do not.
cat catlist.txt|xargs cat > fullcode
I get
cat: app/views/layouts/*: No such file or directory
cat: app/views/accounts/*: No such file or directory
Can someone help me with this. If there is an easier method I am open to all suggestions.
Barb
Your problem is that xargs is not the shell, so the wildcard is being interpreted literally as an star. You'll need to have a shell to do the expansion for you like this:
cat catlist.txt | xargs -I % sh -c "cat %" > fullcode
Note that the * is not recursive in your data file. I assume that was what you meant. If you want the entries to be recursive, that's a little trickier and would need something more like DevNull's script, but that will require that you change your data file a bit to not include the stars.
Are you positive those directories exist?
The problem with doing a cat on a list like that (where you're using wildcards) is that the cat isn't recursive. It will only list the contents of that directory; not any subdirectories.
Here's what I would do:
#!/bin/bash.exe
output="out.txt"
if [ -f "$output" ]
then
rm $output
fi
for file in $(cat catlist.txt)
do
if [ -f "$file" ]
then
echo "$file is a file."
cat $file >> $output
elif [ -d "$file" ]
then
echo "$file is a directory."
find $file -type f -exec cat {} >> $output \;
else
echo "huh?"
fi
done
If the entry listed is a directory, it finds all files from that point on and cats them.
use a while read loop to read your file
while read -r file
do
if [ -f "$file" ]; then
yourcode "$file"
fi
# expand asterix
case "$file" in
*"*" )
for f in $file
do
yourcode "$f"
done
esac
done <"catlist.txt"

Resources