I would like to write a shell script in which I'll take a line input from user,which will contain some xxx.cpp as filename.
I want to get that "xxx" in another variable.
e.g.
if user give input as:
some params path/to/file/xyz.cpp more p/ara/ms
I want to get xyz which occurs before".cpp" and after last occurance of "/" before ".cpp"
Use basename [param] [.ext].
echo `basename $1 .cpp`
where 1 is the index of path/to/file.xyz in the argument list.
Here's a sample bash script to prompt the user for a list of files and filter all the input and display only the base name of files that end in '.cpp' (with .cpp removed) and which are readable
#!/bin/bash
echo Enter list of files:
read list_of_files
for file in $(echo $list_of_files); do
if echo $file | grep '\.cpp$' > /dev/null; then
if [[ -r $file ]]; then
fn=$(basename ${file})
fn=${fn%.*}
echo $fn
fi
fi
done
Related
I have some files stored on a server. I have to get all those files using a pattern and exclude the file which contains the current date as the file name.
Files are given below
/var/tomcat/logs/catalina.2022-05-11.log
/var/tomcat/logs/catalina.2022-05-13.log
/var/tomcat/logs/catalina.2022-05-14.log
/var/tomcat/logs/catalina.2022-05-16.log
/var/tomcat/logs/error_1.log
/var/tomcat/logs/error_2.log
/var/tomcat/logs/error_3.log
/var/tomcat/logs/error_4.log
For this, I have stored patterns in a file and I want to read the pattern of that file and find all files with the help of those patterns.
Pattern Input File content is given below, in below I have used '%Y-%m-%d' to identify the date format so that I can exclude the current date file.
/var/tomcat/logs/catalina.*.log;%Y-%m-%d
/var/tomcat/logs/error_*.log
I have developed a shell script which is given below
#!/bin/sh
pattern_filepath=$1
while IFS= read -r line || [ -n "$line" ]; do
pattern_var="$line"
echo pattern: "$pattern_var"
filepath=""
date_format=""
if [[ $pattern_var == *";"* ]];
then
echo "Semicolons ; separator is there"
filepath=($(echo "$pattern_var" | cut -f1 -d ';'))
echo filepath: "$filepath"
date_format=($(echo "$pattern_var" | cut -f2 -d ';'))
else
echo "Semicolons ; separator is not there"
filepath=$pattern_var
fi
echo "date_format: "$date_format
done < "$pattern_filepath"
Command to run the script
sh /var/monitoring/test.sh "/var/monitoring/pattern" > /var/monitoring/test.log
Inside the log file, I can see, that in the file path variable I am getting the value as a date but that should be with an asterisk instead of a date.
Log file 'test.log'
pattern: /var/tomcat/logs/catalina.*.log;%Y-%m-%d
Semicolons ; separator is there
filepath: /var/tomcat/logs/catalina.2022-05-11.log
date_format: %Y-%m-%d
pattern: /var/tomcat/logs/error_*.log
Semicolons ; separator is not there
date_format:
Please help me with this, how can I achieve this?
Simple, straight to the point. Achieves the requirement, without the complexity of patterns, or lists, or ...
#!/bin/bash
sourcedir="/var/tomcat/logs"
if [[ ! -d "$sourcedir" ]]
then
echo "ERROR: source directory $sourcedir does not exist."
exit 1
fi
targetdir="/tmp/somedir"
if [[ ! -d "$targetdir" ]]
then
echo "ERROR: target directory $targetdir does not exist."
exit 1
fi
# Get the catalina logs
cp "$sourcedir"/catalina.*.log "$targetdir"
# Remove the catalina log for today
filetoremove="$targetdir"/catalina.$(date +%Y-%m-%d).log
if [[ -f "$filetoremove" ]]
then
rm -f "$filetoremove"
fi
# Get the error logs
cp "$sourcedir"/error_*.log "$targetdir"
You can add error checking and recovery for the cp and rm commands.
So my professor and I worked on this for about 2 hours and couldn't figure out what the problem was so I am hoping someone can see what we missed.
askDelete()
{
echo -e " Still want to delete it? (y/n)\n"
read answer
if [ "$answer" = 'y']; then
rm $1
else
echo -e "\nFile was not removed\n"
fi
}
#############################################
clear
#script starts here
echo -e "\n\tCleaner Script\n"
dir=`pwd`
while [ "$choice" -ne 3 ] || [ "$choice" != "quit" ]
do
echo -e "\nEnter 1 to delete by filename or type the word file."
echo -e "\nEnter 2 to delete by a string within a file or type the word string"
echo -e "\nEnter 3 or quit to exit this program.\n"
read choice
case "$choice" in
1|"file") echo -e"Enter the name of the file to delete: "
read file
result=$(find . -name "$file")
if [ -z $result ]; then
echo "File not found"
else
askDelete $file
fi
;;
2|"string") echo -e "Enter the sting to delete the files that contain it: "
read searchstring
result=$(find $dir -type f -perm /400)
echo $result
for file in $result;
do
echo -e "String is $searchstring \nFile is $file"
grep –q "$searchstring" "$file"
if [ $? -eq 0 ]; then
echo "****MATCH****"
askDelete $file
fi
done
;;
3|"quit") echo -e "Exiting program"
break;;
*) echo -e "\nChoice not listed";;
esac
done
and when I do selection 2 I get to the grep and get this error message with my troubleshooting messages.
Enter the sting to delete the files that contain it:
pizza
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/smith.txt
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/data2.txt
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/jones2.txt
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/cleaner.sh
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/jones.txt
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/data.txt
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/smith.txt
grep: pizza: No such file or directory
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/data2.txt
grep: pizza: No such file or directory
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/jones2.txt
grep: pizza: No such file or directory
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/cleaner.sh
grep: pizza: No such file or directory
/home/hopper/z#/CSCI/CSCI330/Assignments/assign4/cleaner.sh:
grep –q "$searchstring" "$file"
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/jones.txt
grep: pizza: No such file or directory
String is pizza
File is /home/hopper/z#/CSCI/CSCI330/Assignments/assign4/data.txt
grep: pizza: No such file or directory
Grep also works just fine outside the BASH script with the absolute paths. Tested the if statement and if I take out the -eq it does work properly because it reads that grep did successfully run just that the directory was not found. From what I can tell it is ignoring my file and instead is using the string search as the directory.
The dash part of the '-q' argument to grep is a special non-ascii character, probably an en-dash in UTF-8, I didn't look too hard. Grep doesn't interpret the en-dash as starting an option and does a search for the string '–q' in the file list. 'pizza' is in the file list.
This can happen easily if you copy code from a web page or a word doc. Anyway, delete the -q and retype it and you script should work better.
Currently I have a shell script which takes parameter as file name.
Something like,
./myshellscript -inpufile=/data/username/Inputfile.xml
I am trying to get the filename using cut
and then checking with -f but that doesn't work when the
-inputfile=~/user/inputfile.xml
I need to verify whether the inputfile is present at location /data/username/
or location which contains ~.
It doesn't take the absolute value.
If I understood correctly:
#!/bin/bash
FILE=`basename /data/username/Inputfile.xml`
if [ -e /data/username/$FILE ];
then
echo "File $FILE exists."
else
echo "File $FILE does not exist."
fi
How about this:
file=$1
# Normalize the file
absdir=$(dirname $file)
fname=$(basename $file)
absname="$absdir/$fname"
echo "Absolute file name: $absname"
if [ -f $absname ] ; then
echo "$absname exists"
else
echo "$absname NOT FOUND"
fi
Sample output:
$ script.sh /tmp/postgres.log
Absolute file name: /tmp/postgres.log
/tmp/postgres.log exists
$ script.sh ~/../../tmp/postgres.log
Absolute file name: /Users/karel/../../tmp/postgres.log
/Users/karel/../../tmp/postgres.log exists
So it does normalize ~ but doesn't normalize ../. Hope this helps..
I have a program that will take user input string and create output files accordingly, for example, "./bashexample2 J40087" this will create output files for all the files in the folder that contain the string J40087. One problem is that if the user does not input anything in the input string it will generate output files for every file inside the containing folder. Is there a way to prevent user to input nothing in the input string? Or maybe spit out some sort of warning saying " please input an input string".
#Please follow the following example as input: xl-irv-05{kmoslehp}312: ./bashexample2 J40087
#!/bin/bash
directory=$(cd `dirname .` && pwd) ##declaring current path
tag=$1 ##declaring argument which is the user input string
echo find: $tag on $directory ##output input string in current directory.
find $directory . -maxdepth 0 -type f -exec grep -sl "$tag" {} \; ##this finds the string the user requested
for files in "$directory"/*"$tag"* ##for all the files with input string name...
do
if [[ $files == *.std ]]; then ##if files have .std extensions convert them to .sum files...
/projects/OPSLIB/BCMTOOLS/sumfmt_linux < "$files" > "${files}.sum"
fi
if [[ $files == *.txt ]]; then ## if files have .txt extensions grep all fails and convert them..
egrep "device|Device|\(F\)" "$files" > "${files}.fail"
fi
echo $files ##print all files that we found
done
I would do something like this:
tag=$1
if [ -z "$tag" ]; then
echo "Please supply a string"
exit 1
fi
You can use $# to know how many arguments has been passed as parameters and then ask if there is at least one argument.
For example
if [ $# -gt 0 ]; then
... your logic here ...
As a note apart, you can read the first parameter passed to your script using $1, and $2 for the second one, and so on.
Hope that helps.
I'm trying to write a script to add the name of a file and the directory path to a text file on a single line.
E.g.
Filename /root/folder/folder/
I've tried:
ls "$1" >> /root/folder/folder/file.txt
pwd >> /root/folder/folder/file.txt
But it shows up on seperate lines.
I did try
ls "$1" && pwd >> ......
but it only pasted the pwd to the text file.
I'm new to Linux so any help would be greatly appreciated.
How about this:
echo "$1 $(pwd)" >> outputfile
Use:
p1=`ls $1`
p2=`pwd`
echo $p1 $p2 >> /root/folder/folder/file.txt
Try:
echo "$1$(pwd)" >> /root/folder/folder/file.txt
Or you can create a new variable with the concatenated string and then echo that:
NewVar="$1$(pwd)"
echo "$NewVar" >> /root/folder/folder/file.txttxt
In the first example you have above, each command inserts a newline. In the second example, the && that you have breaks up the two commands so that the output of the first is not redirected. You can't distribute redirection across the &&, in other words.
A common technique is to use printf (or echo -n, but that's less portable) to avoid writing the newline:
exec >> /root/folder/folder/file.txt
printf "%s " "$1"
pwd
In your example, you use a command to generate the initial data, and a good technique in that case is to use tr to trim the newline
ls "$1" | tr -d '\012'
printf " " # Insert a space
pwd