Hi I have used this code to find the .java file from the given path and generate the list of the .java files from the path to output file,and count total number of tabs and spaces in each java file.now i need to write the two while loops in function and call that function in case statement, how to do this?
Code:
#!/bin/sh
#
output=/home/user/Desktop/file-list.txt
path=/home/user/Desktop
find $path -type f -name \*.java > $output
echo "Generating files list..."
echo "Done"
while IFS= read file
do
if [ -f "$file" ]; then
spaces=$(tr -cd '\s' < "$file" | wc -c);
echo "$spaces spaces in file $file" >> "/home/user/Desktop/space-count.txt"
fi
done < "$output"
echo "Space Count Done!"
while IFS= read file
do
if [ -f "$file" ]; then
tabs=$(tr -cd '\t' < "$file" | wc -c);
echo "$tabs tabs in file $file" >> "/home/user/Desktop/tab-count.txt"
fi
done < "$output"
echo "Tab Count Done!"
Here is an example of case, but the name of the character could be passed to the function
thereby eliminating the need to case the char.
function count_char
{
flist=$1
ch=$2
case $ch in
" ") chName=space;;
"\t") chName=tab;;
esac
while IFS= read file
do
if [ -f "$file" ]; then
tot=$(tr -cd $ch < "$file" | wc -c);
echo "$tot $chName in file $file" >> "/home/user/Desktop/tab-count.txt"
fi
done < "$flist"
}
# setup code, find command here
# ....
count_char $output " "
count_char $output "\t"
Related
I have set of files in a directory. File names are abc-xyz-v01, abc-xyz-v02, abc-xyz,v03 and so on. In the file if there is a key word "name" present then I have to append the last part of the file name e.g. v01 in that line.
This is the code that I have written and it's working fine, but is there any more elegant and better solution. I am new to bash scripting.
#!/bin/bash
# fileinfo.sh
FILES="/home/user/data/test/*"
for file in $FILES
do
echo "$file"
x=0
first=1
linenum=$(awk '/name/{ print NR; exit }' $file)
substr=$(echo $file | cut -d'-' -f 3)
cat $file | while read line; do
x=$(( x+1 ))
if [ $x -eq $first ]
then echo $line > temp.txt
elif [ $x -eq $linenum ]
then echo $line-$substr >> temp.txt
else
echo $line >> temp.txt
fi
done
mv temp.txt $file
done
With gnu-awk, it can be done in one singe command:
awk -i inplace '/name/{split(FILENAME, a, "-"); $0 = $0 "-" a[3]} 1' abc-xyz-v0{1..3}
for the file
$ cat abc-xyz-v01
1
2
name
4
5
this will produce
$ awk '/name/{n=split(FILENAME,a,"-"); $0=$0 "-" a[n]}1' abc-xyz-v01
1
2
name-v01
4
5
you can write your loop
$ for f in ...
do awk ... "$f" > tmp && mv tmp "$f";
...
done
Not sure what you want to do when there is no match, but easy to add an exit status to awk and condition on that.
I am having trouble with my newbie linux script which needs to count brackets and tell if they are matched.
#!/bin/bash
file="$1"
x="()(((a)(()))"
left=$(grep -o "(" <<<"$x" | wc -l)
rght=$(grep -o ")" <<<"$x" | wc -l)
echo "left = $left right = $rght"
if [ $left -gt $rght ]
then echo "not enough brackets"
elif [ $left -eq $rght ]
then echo "all brackets are fine"
else echo "too many"
fi
the problem here is i can't pass an argument through command line so that grep would work and count the brackets from the file. In the $x place I tried writing $file but it does not work
I am executing the script by writting: ./script.h test1.txt the file test1.txt is on the same folder as script.h
Any help in explaining how the parameter passing works would be great. Or maybe other way to do this script?
The construct <<< is used to transmit "the contents of a variable", It is not applicable to "contents of files". If you execute this snippet, you could see what I mean:
#!/bin/bash
file="()(((a)((a simple test)))"
echo "$( cat <<<"$file" )"
which is also equivalent to just echo "$file". That is, what is being sent to the console are the contents of the variable "file".
To get the "contents of a file" which name is inside a var called "file", then do:
#!/bin/bash
file="test1.txt"
echo "$( cat <"$file" )"
which is exactly equivalent to echo "$( <"$file" )", cat <"$file" or even <"$file" cat
You can use: grep -o "(" <"$file" or <"$file" grep -o "("
But grep could accept a file as a parameter, so this: grep -o "(" "$file" also works.
However, I believe that tr would be a better command, as this: <"$file" tr -cd "(".
It transforms the whole file into a sequence of "(" only, which will need a lot less to be transmitted (passed) to the wc command. Your script would become, then:
#!/bin/bash -
file="$1"
[[ $file ]] || exit 1 # make sure the var "file" is not empty.
[[ -r $file ]] || exit 2 # test if the file "file" exists.
left=$(<"$file" tr -cd "("| wc -c)
rght=$(<"$file" tr -cd ")"| wc -c)
echo "left = $left right = $rght"
# as $left and $rght are strictly numeric values, this integer tests work:
(( $left > $rght )) && echo "not enough right brackets"
(( $left == $rght )) && echo "all brackets are fine"
(( $left < $rght )) && echo "too many right brackets"
# added as per an additional request of the OP.
if [[ $(<"$file" tr -cd "()"|head -c1) = ")" ]]; then
echo "the first character is (incorrectly) a right bracket"
fi
I am trying to write a batch file which checks if the file names present in a text file are present in a folder.
I have a folder called PAN where i have a text file named as PRAS_filelist.txt which stores all the file names. And a folder PRAS in which all my files are present.
My requirement is it should scan the folder and at the end, it should populate a error message in a file PRAS_PP_ERROR_LOG. but now it is coming out if any one file is not present since i have used exit.
Below is the code
`rm -f ../SessLogs/PRAS_PP_ERROR_LOG`
for i in `cat ./PAN/PRAS_filelist.txt`
do
file_name=$i
if [ -e ./PAN/PRAS/"$file_name"_* ]
then
if [ -s ./PAN/PRAS/"$file_name"_* ]
then
a=`sed -n '1p' ./PAN/PRAS/"$file_name"_*|cut -d'|' -f1`
b=`sed -n '$p' ./PAN/PRAS/"$file_name"_*|cut -d'|' -f1`
if [ "$a" == "H" ] && [ "$b" == "T" ]
then
trailer_record=`sed -n '$p' ./PAN/PRAS/"$file_name"_*|cut -d'|' -f2`
record_count=`wc -l ./PAN/PRAS/"$file_name"_*|cut -d' ' -f1`
r_c=`expr $record_count - 1`
if [ $trailer_record -eq $r_c ]
then
`cp ./PAN/PRAS/"$file_name"_* ./PAN/PRAS/STANDARDIZE/"$file_name"`
`sed -i '$d' ./PAN/PRAS/STANDARDIZE/"$file_name"`
else
echo "ERROR in file $file_name: Count of records is $r_c and trailer is $trailer_record">../SessLogs/PRAS_PP_ERROR_LOG
fi
else
echo "ERROR in file $file_name: header or trailer is missing">../SessLogs/PRAS_PP_ERROR_LOG
exit 1
fi
else
echo "ERROR in file $file_name: empty file">../SessLogs/PRAS_PP_ERROR_LOG
exit 1
fi
else
echo "ERROR: $file_name doesnot exist">../SessLogs/PRAS_PP_ERROR_LOG
exit 1
fi
done
refactoring your code a bit:
One odd thing is that you claim to have a list of filenames, but then you append an underscore before you check the file exists. Do the actual filenames actually have underscores?
#!/bin/bash
shopt -s nullglob
logfile=../SessLogs/PRAS_PP_ERROR_LOG
rm -f $logfile
while read file_name; do
files=( ./PAN/PRAS/${file_name}_* )
if (( ${#files[#]} == 0 )); then
echo "ERROR: no files named ${file_name}_*"
continue
elif (( ${#files[#]} > 1 )); then
echo "ERROR: multiple files named ${file_name}_*"
continue
fi
f=${files[0]}
if [[ ! -s $f ]]; then
echo "ERROR in file $f: empty file"
continue
fi
a=$(sed '1q' "$f" | cut -d'|' -f1)
b=$(sed -n '$p' "$f" | cut -d'|' -f1)
if [[ "$a" != "H" || "$b" != "T" ]]; then
echo "ERROR in file $f: header or trailer is missing"
continue
fi
trailer_record=$(sed -n '$p' "$f" | cut -d'|' -f2)
r_c=$(( $(wc -l < "$f") - 1 ))
if (( trailer_record == r_c )); then
sed '$d' "$f" > ./PAN/PRAS/STANDARDIZE/"$file_name"
else
echo "ERROR in file $f: Count of records is $r_c and trailer is $trailer_record"
fi
done < ./PAN/PRAS_filelist.txt | tee $logfile
I have a different HTML files in a folder. How to rename the files so that they have the names of:
1.html
2.html
3.html
...
This can make it:
i=1
for file in /your/folder/*
do
mv $file ${i}.html
i=$((i+1)) #((i++)) was giving errors (see comments)
done
It loops through all files in /your/folder and renames them according to the number $i that keeps increasing.
Here is my script
#!/bin/sh
#
# batchrename - renames files like 01.ext, 02.ext ...
#
# format : batchrename <list of files>
# or: -r <extension> <<list of files> or <dir>>
# -r - recoursively
counter=0
extrec=""
if [ "$#" -lt "1" ]; then
echo -e "\n\t\tUsage:\n\tbatchrename [opt]\nopt:"
echo -e "-r <ext> <folder> (or file list) -- renames recoursively ALL files"
echo -e "\tin folder <folder> (or by file list given) with extension .<ext>"
echo -e "<folder> -- renames ALL files in folder given"
echo -e "<file list> -- renames ALL files of given filelist.\n\n"
exit 0
fi
Name="$*"
if [ "$1" = "-r" ]; then
extrec="$2"
shift
shift
Name="$*"
[ "$Name" = "" ] && Name="./"
fi
echo -e "\n\t\t\tRENAMING"
for file in $Name
do
file=`echo "$file" | sed "s/<>/ /g"`
if [ -d "$file" ];then
echo -e "\nDiving into \033[38m $file \033[39m"
cd "$file"
if [ "$extrec" != "" ]; then
batchrename -r $extrec `ls -1 | sed "s/\ /<>/g"`
else
batchrename `ls -1 | sed "s/\ /<>/g"`
fi
cd ../
continue
fi
ext=`ext "$file"`
if [ "$ext" = "ion" ]; then
continue
fi
if [ "$extrec" = "" -o "$ext" = "$extrec" ];then
counter=`expr $counter + 1`
echo -e "Progress: $counter files\r\c"
mv "$file" "rnmd$counter.$ext"
fi
done
echo -e "\n\n\t\t\tENDING"
digits=`echo $counter|awk '{print length ($0)}'`
cnt=1
while [ $digits -gt $cnt ]
do
f=`ls -S -1|grep "rnmd[0-9]\{$cnt\}\."`
rename rnmd rnmd0 $f
cnt=`expr $cnt + 1`
done
if [ "$counter" -gt "0" ]; then
rename rnmd "" rnmd*
fi
echo -e "\n\t\t\tDone !!!\n"
After renaming all your files will looks like 001.file, 002.file, ... and so on. Amount of leading zeros depends on amount of files. So, after renaming ls will show right order of files!
It use intermediate script ext:
#!/bin/sh
#
# ext - returns file suffix (case-unsensitive)
#
File="$*"
if [ -d "$File" ]; then
echo ""
exit 0
fi
EXT=`echo $File|sed 's/.\{1,\}\.//g'`
if [ "$EXT" = "$File" ]; then
EXT=""
fi
echo $EXT| tr '[:upper:]' '[:lower:]'
Here is a similar code, just to add to rename with the same prefix and append an incremental value
declare -i x=1
for f in $(find -type f); do
mv -v $f ${f%/*}/change_me_$x ;
x=$x+1;
done
I have created a script which creates two files and reverses their contents if both the files are different. I cant understand how to resolve this error :
[: my-filename: unexpected error in shell programming
Code:
echo "Enter first filename :"
read file1
echo "Enter second filename:"
read file2
echo "Enter content of file 1 : "
gedit $file1
echo "Enter content of file 2 : "
gedit $file2
check=" "
x=` cmp $file1 $file2 `
if [ $x -eq $check ]
then
echo "Both files are same"
rm $file2
echo "Redundant file removed!!!"
else
echo "They are different"
fi
tac $file1 | cat > temp1
rev temp1 | cat > temp11
tac $file2 | cat > temp2
rev temp2 | cat > temp22
mv temp11 $file1
mv temp22 $file2
echo "Content of both the files reversed"
You can use cmp directly from the if statement
if cmp -s $file1 $file2
then
echo "Both files are same"
rm $file2
echo "Redundant file removed!!!"
else
echo "They are different"
fi
You have to give which shell you are using.
But I think if [ $x -eq $check ] cause the problem. Your shell interpret the file name which include the '-' as a switch. you can either rename my-filename to myfilename or double quote the $x:
if [ "$x" -eq "$check" ]
In bash, the logical operators -eq -ne -gt -lt -ge -le are specific for numeric arguments. For comparing string you can simply use
if [ $x = $check ]; then
# do whatever
fi