4

I am writing my first code in bash. I am stuck from 2 hours. This is my code:

#!/bin/bash declare -i l=0 declare -i d=0 declare -i s1=0 declare -i s2=0 declare -i t=0 declare -i o=0 declare -i p=0 for i in demo_room/subject_1/?* do if [ "${i:0:1}" = "l" ]; then ((l++)); echo "l=$l" python motempl_n.py $i $l elif [ "${i:0:1}" = "d" ]; then ((d++)); echo "d=$d" python motempl_n.py $i $d elif [ "${i:0:1}" = "o" ]; then o=$((o+1)); echo "o=$o" python motempl_n.py $i $o elif [ "${i:0:1}" = "p" ]; then p=$((p+1)); python motempl_n.py $i $p elif [ "${i:0:1}" = "t" ]; then t=$((t+1)); python motempl_n.py $i $t elif [ "${i:0:7}" = "slide_1" ]; then s1=$((s1+1)); python motempl_n.py $i $s1 #elif [ "${i:0:7}" == 'slide_2' ] else s2=$((s2+1)); python motempl_n.py $i $s2 fi done 

So I am having a folder demo_room/subject_1. In this folder I have 140 avi videos their names are:

20 videos have name: dislike_01 to dislike_20

20 videos have name: like_01 to like_20

20 videos have name: ok_01 to ok_20

20 videos have name: point_01 to point_20

20 videos have name: slide_1_01 to slide_1_20

20 videos have name: slide_2_01 to slide_2_20

20 videos have name: take_a_picture_01 to take_a_picture_1_20

What I want to do is first find the class of the input video then give its occurrence as input to python file. First 20 videos of subject_1 folder are dislike one so this code works fine but the 21st video is like_01 but the parameter it passes to the python code is 21.

But it should be 1 because this is first video of like class in the for loop. And each time it prints value of $d. It means each time it goes in 2nd if condition. In the python code I can verify that the name of the video is like_01 but second value passed is 21. Why? This happens for all the 140 videos.

4
  • You should also quote your variables and remove the unnecessary ;'s (all of them)
    – jesse_b
    CommentedJun 8, 2018 at 13:46
  • 3
    Your first bash script? Wow, you've already doing great!CommentedJun 8, 2018 at 13:57
  • The echo inside [ ... ] must be a typo, right? Also, you're inconsistent in how you increment your counters.
    – Kusalananda
    CommentedJun 8, 2018 at 20:49
  • @Kusalananda that was typo fixed it. My first approach was using echo, but I got error [ too many argumentsCommentedJun 9, 2018 at 4:20

3 Answers 3

8

Your $i will contain the full path (demo_room/subject_1/file), so will always start with d.

You could do something like:

case "${i##*/}" in (d*) ...;; (l*) ...;; (slide1_*) ...;; ... esac 

Where ${i##*/} is $i with the leading part matching */ removed.

Also beware that parameter expansions need to be quoted in sh/bash:

python motempl_n.py "$i" "$s2" 
1
  • Thanks it worked, I made some changed like passing ${i##*/} instead of $i in each case and also in my python file changed input video location.CommentedJun 8, 2018 at 16:47
7

While your code is well written, there's a lot of duplication. Here's a more condensed version:

#!/bin/bash declare -A count for file in demo_room/subject_1/*; do base=${file##*/} case $base in slide_[12]*) key=${base:0:7};; [ldopt]*) key=${base:0:1};; *) ;; # other types ignored esac (( count[$key]++ )) echo "$key=${count[$key]}" python motempl_n.py "$file" "${count[$key]}" done 

I'm using an associative array instead of distinct integer variables, but fortunately bash arithmetic handles (( an_unset_variable++ )) gracefully and assigns "1" to the variable.

Note that the ? in your ?* was redundant as file names always contain at least one character, so there's no file that * (0 or more characters) would match and ?* (1 or more characters) wouldn't.

2
  • That was for directory like . and..CommentedJun 8, 2018 at 17:08
  • * will not match dot-files unless you shopt -s dotglob or set GLOBIGNORE to certain values.CommentedJun 8, 2018 at 17:47
1

Your $i variable always start with a d: demo_room … …
You need to extract the file name. And since we are extracting, we may as well extract both the name and the number of the file.

Thus, a shorter version of your script could be:

#!/bin/bash declare -Ai count for i in ./demo_room/subject_1/?*; do j=${i##*/} ; name=${j%_*} ; number=${j##*_} ((count[$name]++)) echo \ python motempl_n.py "$i" "${count[$name]}" done echo "List of keys: " "${!count[@]}" 

This script use only one array variable count, the list of (automatically) keys used (from $name) is printed at the end of the script.

Comment out the echo \ line once you like how the script works to actually execute the commands.

4
  • Will $name and $number work for the files slide_1_xx?And also passing $j instead of $i will be more helpful because I just need file name inside the python file and not path because that I added manually.CommentedJun 9, 2018 at 4:14
  • 1
    At least: Did you try the script? … work for the files slide_1_xx? It did when I tested it. … $i will be more helpful Then, use it, no problem.
    – user232326
    CommentedJun 9, 2018 at 4:58
  • well I didn't try it but had doubt so asked it.But problem is solved thanksCommentedJun 9, 2018 at 5:00
  • @Debian_yadav If you do not try and learn: It is your loss, not mine. have a nice day.
    – user232326
    CommentedJun 9, 2018 at 5:59

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.