So I can almost guarantee this is a dumb question but I just can't figure this out. I'm trying to count how many times I've indexed files. I need to increment a counter every time I find a pdf file that matches certain criteria (it's metadata must contain 3 specific values). The variable in question is indexCount and I've marked the line where I'm trying to increment it with #NOT SURE ABOUT THIS LINE
index() {
for file in *
do
[ -d "$file" ] && (cd "$file"; index)
oldPath=$(pwd)
if [ "$( echo "$file" | grep -E '.*\.pdf' )" ]; then
metadata="$(pdftk "$file" dump_data)"
echo "$metadata" | $(grep -e '^InfoKey: Title' >/dev/null 2>&1) && echo "$metadata" | $(grep -e '^InfoKey: Author' >/dev/null 2>&1) && echo "$metadata" | $(grep -e '^InfoKey: CreationDate' >/dev/null 2>&1)
if [ $? -eq 0 ]; then
path="$(pwd)/""$file"
title=$(getAttr "$metadata" '^InfoKey: Title')
author=$(getAttr "$metadata" '^InfoKey: Author')
creation=$(getAttr "$metadata" '^InfoKey: CreationDate')
authorsArray=($(getAuthors "$author"))
for auth in "${authorsArray[#]}";
do
createFolders "$auth" "$creation" "$title" "$path" "$oldPath"
done
$1=$(($1+1)) #NOT SURE ABOUT THIS LINE
fi
fi
done
echo $1
}
indexCount=0
index $indexCount
The correct syntax is:
var=$((var+1))
So instead of
$1=$(($1+1))
you should use a variable name plus the syntax I indicate above. In general, remember bash variables are set without the $ and used with it.
Quoting from Charles Duffy:
If targeting bash as opposed to POSIX sh, there's also the option of (( ++var )) or (( var += 1 ))
Related
I am trying to search content of file 1 into file 2 and if the content is found then store in found.csv file or store in notfound.csv file
Below is my code,
cd /mnt/data/dobiminer/scripts
usage="Usage:sh scriptname.sh 'ToSearchFile' 'MainSearchFile' 'CR' "
Date=`date +%m%d%y%H%M%S`
File=$(<$2)
echo "File Input $2"
echo $File
if [ $# != 3 ]
then
echo $usage
exit 1
else
echo > "$3-Found-$Date.csv"
echo > "$3-NotFound-$Date.csv"
for MasterClip in `cat $1`
do
echo $MasterClip
String=$(echo "$File" | grep -x $MasterClip)
echo $String
if [ -z $String ];
then
echo "NotFound"
echo $MasterClip >> "$3-NotFound-$Date.csv"
else
echo "Found"
echo $MasterClip >> "$3-Found-$Date.csv"
fi
done
fi
My guess is that the below line of code is not working, as whenever I am running the code, the string value is empty only. It is not catching the search value into it.
String=$(echo "$File" | grep -x $MasterClip)
echo $String
I tried multiple things but not sure where I am going wrong.
THanks for helping me out
I searched and couldn't find anything, maybe I can't understand the problem properly.
I have a bash function who read files in current dir and sub dir's, I'm trying to arrange the text and analyze the data but somehow I'm losing lines if I'm using pipeline.
the code:
function recursiveFindReq {
for file in *.request; do
if [[ -f "$file" ]]; then
echo handling "$file"
echo ---------------with pipe-----------------------
cat "$file" | while read -a line; do
if (( ${#line} > 1 )); then
echo ${line[*]}
fi
done
echo ----------------without pipe----------------------
cat "$file"
echo
echo num of lines: `cat "$file" | wc -l`
echo --------------------------------------
fi
done
for dir in ./*; do
if [[ -d "$dir" ]]; then
echo cd to $dir
cd "$dir"
recursiveFindReq "$1"
cd ..
fi
done
}
the output is:
losing lines even when they meet requirements
I marked with 2 red arrows the place I'm losing info
Sorry for asking this question again. I have already received answer but with using find but unfortunately I need to write it without using any predefined commands.
I am trying to write a script that will loop recursively through the subdirectories in the current directory. It should check the file count in each directory. If file count is greater than 10 it should write all names of these file in file named "BigList" otherwise it should write in file "ShortList". This should look like:
---<directory name>
<filename>
<filename>
<filename>
<filename>
....
---<directory name>
<filename>
<filename>
<filename>
<filename>
....
My script only works if subdirectories don't include subdirectories in turn.
I am confused about this because it doesn't work as I expect.
Here is my script
#!/bin/bash
parent_dir=""
if [ -d "$1" ]; then
path=$1;
else
path=$(pwd)
fi
parent_dir=$path
loop_folder_recurse() {
local files_list=""
local cnt=0
for i in "$1"/*;do
if [ -d "$i" ];then
echo "dir: $i"
parent_dir=$i
echo before recursion
loop_folder_recurse "$i"
echo after recursion
if [ $cnt -ge 10 ]; then
echo -e "---"$parent_dir >> BigList
echo -e $file_list >> BigList
else
echo -e "---"$parent_dir >> ShortList
echo -e $file_list >> ShortList
fi
elif [ -f "$i" ]; then
echo file $i
if [ $cur_fol != $main_pwd ]; then
file_list+=$i'\n'
cnt=$((cnt + 1))
fi
fi
done
}
echo "Base path: $path"
loop_folder_recurse $path
How can I modify my script to produce the desired output?
This bash script produces the output that you want:
#!/bin/bash
bigfile="$PWD/BigList"
shortfile="$PWD/ShortList"
shopt -s nullglob
loop_folder_recurse() {
(
[[ -n "$1" ]] && cd "$1"
for i in */; do
[[ -d "$i" ]] && loop_folder_recurse "$i"
count=0
files=''
for j in *; do
if [[ -f "$j" ]]; then
files+="$j"$'\n'
((++count))
fi
done
if ((count > 10)); then
outfile="$bigfile"
else
outfile="$shortfile"
fi
echo "$i" >> "$outfile"
echo "$files" >> "$outfile"
done
)
}
loop_folder_recurse
Explanation
shopt -s nullglob is used so that when a directory is empty, the loop will not run. The body of the function is within ( ) so that it runs within a subshell. This is for convenience, as it means that the function returns to the previous directory when the subshell exits.
Hopefully the rest of the script is fairly self-explanatory but if not, please let me know and I will be happy to provide additional explanation.
I have shell Script written which does a job of comparing two files and and gives me result in a HTML format for defects. But i want to improve it so that i can only get modified files defects instead of legacy defects also. I am using this script to get Coverity report.
while read line; do
n=$((++n))
if echo $line | grep '^[[:space:]]*>' &>/dev/null; then
if [ $(($n % 2)) -eq 1 ]; then
# TODO somehow get proper defect number from html
# echo "Defect num: $(($n/2 + 1))"
def_num=$((++def_num))
fi
echo $line | sed -n -e 's/>[[:space:]]*\(.*\)/\1/p'
if [ $(($n % 2)) -eq 0 ]; then
echo "-------------------------------"
fi
done < <(diff -y -W 200 ./cov-results-base/result.filt ./cov-results-changed/result.filt)
echo "==============================="
echo
echo "Number of defects in old code: $(tac cov-results-base/summary.xml |
sed -n '/num/{s|<num>\(.*\)</num>|\1|p; q;}')"
echo "Number of defects in new code: $(tac cov-results-changed/summary.xml |
sed -n '/num/{s|<num>\(.*\)</num>|\1|p; q;}')"
This enables you to get the last modification time of a file and the compare with the current time.
now=`date +%s`
modified=`stat -c "%Y" $file`
if [ $(($now-$modified)) -gt 0 ]; then
echo "not modified";
else
echo "modified";
fi
I hope that this is what you wanted.
I'm trying to imitate the bash file completion.
Suppose I have the following files:
test1
test2
With an input string of "te" I would like to get the output "test"
This is my current attempt ($c is the input string):
l=1
q="$c"
for j in $(ls -A | grep "^$c"); do
if [ "${j/$c}" != "$j" ]; then
n=$(ls -A | grep ^$j | wc -l)
if [ $n -gt $l ]; then
q="$j"
fi
fi
done
c="$q"
echo $c
Thanks for any help
I tend to think there is no a way to get this from completion engine since it’s not a part of GNU Bash but Readline. But at least we can get list of possible completions with compgen. And an inmplementaion of finding longest common prefix should not be problem. So...
#!/bin/bash
SCRIPTNAME="${0##*/}"
USAGE="Usage: $SCRIPTNAME <prefix>
Print common prefix of possible file name completions. Like <TAB> but to
stdout."
(( $# == 1 )) || { printf >&2 '%s\n' "$USAGE"; exit 1; }
PREFIX="$1"
commonprefix() {
(( $# >= 2 )) || {
echo "$1"
return 0
}
local -i i N M
for ((i=0; i<=${#1}; i++)); do
for ((N=1; N<=$#-1; N++)); do
let M=$N+1
[[ ${!N:i:1} == ${!M:i:1} ]] || break 2
done
done
echo "${1:0:i}"
}
readarray -t COMPLETIONS < <(compgen -f "$PREFIX")
commonprefix "${COMPLETIONS[#]}"
Although Dmitry Alexandrov already provided a better solution, I still would like to post my own one which I made while waiting for the answers:
l=1
while [ -n $l ]; do
l=${#c}
a=$(ls -A | grep "^$c" | wc -l)
q=$c
for i in $(ls -A | grep "^$q"); do
if [ $i == $q ]; then
unset l
break
else
v=$(ls -A | grep "^$q${i:$l:1}" | wc -l)
if [ $v == $a ]; then
q="$c${i:$l:1}"
break
fi
fi
done
if [ $c == $q ]; then break; fi
c=$q
done
echo $c
It works with all of my tests, but it's slow (although it could be optimized).
Just to show that you were thinking in correct direction, I made your code work:
#!/bin/bash
c=$1
q="$c"
for j in $c*; do
if [ "${j/$c}" != "$j" ]; then
startn=$(ls -1A | grep -c "^${j:0:$((${#c} + 1))}")
for (( i=${#c}; i <= ${#j}; i++ )); do
n=$(ls -1A | grep -c "^${j:0:$i}")
if [ "$n" -lt "$startn" ]; then
q="${j:0:$((i - 1))}"
elif [ "$n" -le "$startn" ]; then
q="${j:0:$i}"
fi
done
fi
done
c="$q"
echo "$c"
But, it's just a proof of concept, don't use it. See answer by Dmitry Alexandrov for a good solution.