1
\$\begingroup\$

I have a directory structure like bellow.

.
├── Course 1
│   ├── 1 - Introduction
│   │   ├── 01-First Video.mp4
│   │   ├── 02-Second Video.mp4
│   │   ├── 03-Third Video.mp4
│   ├── 2 - Chapter 1
│   │   ├── 05-Nth Video.mp4
│   │   ├── 06-Nth1 Video.mp4
│   │   └── 07-Nth2 Video.mp4
│   ├── 3 - Chapter 2
│   │   ├── 08-Nth Video.mp4
│   │   ├── 09-Nth1 Video.mp4
│   │   └── 10-Nth2 Video.mp4
│   ├── 4 - Analysis
│   │   ├── 11-Nth Video.mp4
│   │   ├── 12-Nth1 Video.mp4
│   │   └── 13-Nth2 Video.mp4
│   ├── 5 - Conclusion
│   │   ├── 14-Nth Video.mp4
│   │   ├── 15-Nth1 Video.mp4
│   │   └── 16-Nth2 Video.mp4
├── Course 2
│   ├── 1 - Introduction
│   │   ├── 01-First Video.mp4
│   │   ├── 02-Second Video.mp4
│   │   ├── 03-Third Video.mp4
│   ├── 2 - Chapter 1
│   │   ├── 05-Nth Video.mp4
│   │   ├── 06-Nth1 Video.mp4
│   │   └── 07-Nth2 Video.mp4
│   ├── 4 - Analysis
│   │   ├── 11-Nth Video.mp4
│   │   ├── 12-Nth1 Video.mp4
│   │   └── 13-Nth2 Video.mp4
│   ├── 5 - Conclusion
│   │   ├── 14-Nth Video.mp4
│   │   ├── 15-Nth1 Video.mp4
│   │   └── 16-Nth2 Video.mp4
├── Course 3
│   ├── 1 - Introduction
│   │   ├── 02-First Video.mp4
│   │   ├── 03-Third Video.mp4
│   ├── 2 - Chapter 1
│   │   ├── 05-Nth Video.mp4
│   │   └── 07-Nth2 Video.mp4
│   ├── 4 - Analysis
│   │   ├── 11-Nth Video.mp4
│   │   ├── 12-Nth1 Video.mp4
│   ├── 5 - Conclusion
│   │   ├── 14-Nth Video.mp4
│   │   ├── 15-Nth1 Video.mp4
│   │   └── 16-Nth2 Video.mp4

I want to find if any files are missing in the directories.

The code that i am using to solve this problem is:

#!/usr/bin/env bash

previousname="Placeholder"
nextfilenumber=1
find . -type f -name "*.mp4" | sort --version-sort | while read -r line ; do
    coursename=$(echo $line | cut -d/ -f2)
    if [[ "$previousname" != "$coursename" ]]; then
        nextfilenumber=2
        previousname=$coursename
    else
        filename=${line##*/}
        # https://stackoverflow.com/a/24777667/1772898
        filenumber=$((10#${filename%%-*}))
        nextfilenumber="$((nextfilenumber+1))"
        temp="$((filenumber+1))"
        if [[ $temp -ne $nextfilenumber ]]; then
            echo "File(s) Before \"$coursename\"\'s \"$filename\""
            nextfilenumber="$((nextfilenumber+1))"
        fi
    fi
done

How can I make this code better?

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Improve usability

For the example input, the script produces the following output for Course 2:

File(s) Before "Course 2"\'s "05-Nth Video.mp4"
File(s) Before "Course 2"\'s "11-Nth Video.mp4"
File(s) Before "Course 2"\'s "12-Nth1 Video.mp4"
File(s) Before "Course 2"\'s "13-Nth2 Video.mp4"

The first line I understand: a file with number 04 is missing, before seeing 05.

The rest of the lines look a bit strange: I understand the objection about the file with number 11, since files with number 08, 09 and 10 are missing before that.

I think it would be more user friendly to print something like:

Expected a file with number 4, got: Course 2/2 - Chapter 1/05-Nth Video.mp4
Expected a file with number 8, got: Course 2/4 - Analysis/11-Nth Video.mp4

As another example, consider the output for Course 3:

File(s) Before "Course 3"\'s "03-Third Video.mp4"
File(s) Before "Course 3"\'s "05-Nth Video.mp4"
File(s) Before "Course 3"\'s "07-Nth2 Video.mp4"
File(s) Before "Course 3"\'s "11-Nth Video.mp4"
File(s) Before "Course 3"\'s "12-Nth1 Video.mp4"
File(s) Before "Course 3"\'s "14-Nth Video.mp4"
File(s) Before "Course 3"\'s "15-Nth1 Video.mp4"

Similar to the previous example, this looks a bit strange because a file with number 1 is missing, a file with number 2 is present, but the message mentions a file with number 3.


Also note the message prints \' instead of simply '.

Simplify the number comparison logic

Instead of this:

nextfilenumber="$((nextfilenumber+1))"
temp="$((filenumber+1))"
if [[ $temp -ne $nextfilenumber ]]; then
    echo "File(s) Before \"$coursename\"\'s \"$filename\""
    nextfilenumber="$((nextfilenumber+1))"
fi

This is shorter and equivalent:

if [[ $filenumber -ne $nextfilenumber ]]; then
    echo "File(s) Before \"$coursename\"\'s \"$filename\""
    nextfilenumber="$((nextfilenumber+1))"
fi
nextfilenumber="$((nextfilenumber+1))"

The original unnecessarily computes the next file number in the poorly named temp variable.

Remove redundant quotes

The double-quotes in expressions like this are unnecessary:

nextfilenumber="$((nextfilenumber+1))"

They are harmless, so it's ok to keep them, but then it's better to apply it consistently everywhere (example where not used: filenumber=$((10#${filename%%-*}))).

Beware of running commands in a loop

The script runs cut in a loop to extract a path component. Running commands in a loop can make scripts very slow. In this example you can achieve the same result using shell builtins:

IFS=/ read _ coursename _ <<< "$line"

Improve variable names

Renaming previousname to previous_coursename would make the connection with coursename more clear.

Alternative implementation

Addressing the above issues and putting it together:

#!/usr/bin/env bash

previous_course_name=
expected_file_number=1
find . -type f -name "*.mp4" | sort --version-sort | while read -r line ; do
    IFS=/ read _ current_course_name _ <<< "$line"
    if [[ "$previous_course_name" != "$current_course_name" ]]; then
        expected_file_number=1
        previous_course_name=$current_course_name
    fi

    filename=${line##*/}
    # https://stackoverflow.com/a/24777667/1772898
    file_number=$((10#${filename%%-*}))
    if [[ $file_number != $expected_file_number ]]; then
        echo "Expected a file with number $expected_file_number; got: $line"
    fi
    ((expected_file_number = file_number + 1))
done

This produces output:

Expected a file with number 4; got: ./Course 1/2 - Chapter 1/05-Nth Video.mp4
Expected a file with number 4; got: ./Course 2/2 - Chapter 1/05-Nth Video.mp4
Expected a file with number 8; got: ./Course 2/4 - Analysis/11-Nth Video.mp4
Expected a file with number 1; got: ./Course 3/1 - Introduction/02-First Video.mp4
Expected a file with number 4; got: ./Course 3/2 - Chapter 1/05-Nth Video.mp4
Expected a file with number 6; got: ./Course 3/2 - Chapter 1/07-Nth2 Video.mp4
Expected a file with number 8; got: ./Course 3/4 - Analysis/11-Nth Video.mp4
Expected a file with number 13; got: ./Course 3/5 - Conclusion/14-Nth Video.mp4
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.