I'm working on a bash scripts that will essentially shift the entire contents of a directory, where the filenames all start with a number (0001, 0002, etc). I'm iterating in reverse order through those files to shift the last one down first.
I have one function that iterates through the files and calls another function to actually shift them. When I call the second function, it short-circuits the for loop and exits. I can't figure out why.
validation_dir="scripts/validation"
content_directories=($validation_dir "tutorials")
function shift_contents() {
local start_index=$1
local positions=$2
local files=(${validation_dir}/*)
for ((i=${#files[@]}-1; i>=0; i--)); do
# Only gets called once
echo $i
local f="${files[$i]}"
local old_index=$(echo $f | tr -dc '0-9' | sed -e 's/^0*//')
if [ "$old_index" -lt "$start_index" ]
then
# Only start when we're at the start index
continue
fi
local new_index=$((old_index + positions))
# When this is called, it exits the loop
move_exercise $old_index $new_index
done
}
Here's the function that does the shifting:
function move_exercise() {
local start_index=$1
local end_index=$2
local start_prefix=$(echo_filename_prefix $start_index)
local end_prefix=$(echo_filename_prefix $end_index)
for i in ${content_directories[@]}; do
start_file_glob="${i}/${start_prefix}*"
for f in $start_file_glob; do
if [ -e $f ]
then
start_filename=$f
else
log_error "No content found with index ${start_index}"
exit 1
fi
break
done
end_file_glob="${i}/${end_prefix}*"
if [ -e $end_file_glob ]
then
log_error "Content was already found for end index ${end_index}: ${end_file_glob}"
exit 1
fi
# Generate the new file name
new_filename="${start_filename/$start_prefix/$end_prefix}"
# We get down here once
echo $start_filename $new_filename
done
return
}
It looks like the second function is causing the first to exit early, but I don't see how that could happen. See what's going on?
EDIT:
When I run with bash -x script.sh, it ends with the following output when it should have one more iteration:
+ echo path/to/second-to-last-file new-path
+ return
+ (( i-- ))
+ (( i>=0 ))
Does that imply that it's failing the for loop condition check? If so, how could move_exercise impact that? If I comment out that line, it works as expected.
bash -x script.sh. It's often the best debugging tool for bash scripts.[ -e $globexpr ]to tell you whether at least one file matching the given glob expression actually exists. However, that's not what it does in practice. If you have more than match, then you end up with a command line[ -e file1 file2 ], which is insofar as[is concerned simply invalid syntax.dir='/directory/with spaces'-- you can expand"$dir"/*.txtwithout any problem, butglob=$dir/*.txtand then expanding$globwill create/directory/withas the first result, andspaces/*.txtas the second (unless you also have a directory namedspaceswith files matching*.txtin it, in which case those would result).