Passing sequential list to for loop [duplicate] - bash

This question already has answers here:
How do I iterate over a range of numbers defined by variables in Bash?
(20 answers)
Closed 4 years ago.
I have a list of files to put through a for loop. They are named
FA2_00032.png, FA2_00033.png, etc
I have variables $imID which contains FA2 string, $startFrame which contains the start frame (e.g. 00034) and $endFrame which contains to end frame (e.g. 00894).
I have managed to get the list of relevant files using:
eval echo ${imageID}_{${startFrame}..${endFrame}}.png;
This outputs
FA2_00034 FA2_00035 FA2_00036 etc
But now I need to pass this to the for loop. That is,
for file in *the above list*
where *the above list* is the block quoted list above. $file should contain FA2_00034, FA2_00035, etc for use in the for loop.

Use a C-style for loop, not eval+{...}, for tasks like this. printf can be used to assemble the file name from the current integer. The syntax 10#$foo ensures that the value of $foo is treated as a decimal (not an octal) number if it includes leading 0s.
imageID=FA2
startFrame=00034
endFrame=00894
for ((i=10#startFrame; i<=10#$endFrame; i++)); do
printf -v file '%s_%05d.png' "$imageID" "$i"
echo "Operating on $file" >&2
done

Related

Using variables inside for loops [duplicate]

This question already has answers here:
When to wrap quotes around a shell variable?
(5 answers)
Closed 2 years ago.
I'm trying to compare sizes of files inside two directories.
My problem is that when I store the sizes of the files inside of a "for" loop, my variable takes all the sizes at once instead of taking them one by one.
Here is the part of my code that is problematic :
for dir1Files in dir1/*
do
sizeFile1=`stat -c%s $dir1Files`
for dir2Files in dir2/*
do
sizeFile2=`stat -c%s $dir2Files`
diffSize=$((sizeFile1-sizeFile2))
echo "$diffSize"
done
done
I realised, thanks to set -x, that my variables sizeFile1 and sizeFile2 are not integers. Instead, they are a few lines long and contain the sizes of my files in directories, with "one line = one integer", if that makes sense.
For example, with three files in dir1, my variable sizeFile1 is :
12500
14534
23000
What I would like is for my variable to vary from 12500 to 14534 to 23000. How should I do that ? I'm guessing I need to change my "for" into something else ?
Thanks in advance.
Nothing in this is broken 100% of the time, but it certainly can be broken if run with unusual filenames present. To make this code more robust:
Use quotes whenever you expand a variable. This prevents a file named dir1/ * (with the space in its name) from being replaced with a list of all files in the current directory when generating a stat command line.
Use shopt -s nullglob to make the loops not run at all when no glob matches exist, instead of running with the glob expression as a filename itself.
shopt -s nullglob # prevent dir1/* from ever evaluating to itself
for dir1File in dir1/*; do
sizeFile1=$(stat -c%s "$dir1File")
for dir2File in dir2/*; do
sizeFile2=$(stat -c%s "$dir2File")
diffSize=$((sizeFile1-sizeFile2))
echo "$diffSize"
done
done

Store each word from a file in an array (in bash) [duplicate]

This question already has answers here:
Creating an array from a text file in Bash
(7 answers)
Closed 2 years ago.
I'm trying to store each word from a file (named f1.txt) in an array (in bash), and then I want to print each element of the array. I tried something like this:
n=0
for varWord in $(cat f1.txt);
do
word[$n]=$varWord
$((n++))
done
for((i=0;i<n;i++));
do
echo $((word[i]))
done
I've also tried this (In fact, it was my first approach, as I would also prefer not to use an additional variable -- varWord, like I did above):
n=0
for word[$n] in $(cat f1.txt);
do
$((n++))
done
for((i=0;i<n;i++));
do
echo $((word[i]))
done
read -r -d '' -a words <inputfile.txt
That's all it needs.

Shuffling doesn't actually save into array? [duplicate]

This question already has answers here:
How do I set a variable to the output of a command in Bash?
(15 answers)
Copying a Bash array fails
(2 answers)
Closed 3 years ago.
I'm new to shell script and am having an issue with the shuf function.
This is my code
declare -a myarray=( 'A' 'B' 'C' 'D' 'E' 'F' )
myarray = $(shuf -e "${myarray[#]}")
echo "$myarray"
I make an array containing the six characters. I then shuffle them randomly, and print them out. My issue is that if I were to add another line, for example
echo ${myarray[2]}
This doesn't actually print the randomly sorted character in the 3rd position. Instead, it will always print 'C'. How can I actually save the sorted array? Do I need to make another array?
Thank you very much
Arrays in bash are defined with (). Bash is not statically typed, so setting myarray equal to some output of characters will do just that, making it a string you can echo with echo $myarray to see the full output.
You need to wrap your output in parens to make it clear to bash that your new myarray should also be an array:
myarray=($(shuf -e "${myarray[#]}"))

Ambiguous redirect error bash [duplicate]

This question already has answers here:
Getting an "ambiguous redirect" error
(14 answers)
Closed 5 years ago.
There have been other posts regarding this problem, but none answer my question.The other posts mention adding quotes, but that leads to an EOF while matchign error.
I am writing a bash script that contains the following line, but when I execute, I get an error message which reads "Ambiguous redirect." Why?
done < $(cat $textfile1 $textfile2) >> $outputfile
At barest minimum, you need more quotes.
# PROBABLY NOT WHAT YOU WANT:
# Read from an input file whose name is generated by concatenating the contents of the
# files named in textfile1 and textfile2 variables
done < "$(cat -- "$textfile1" "$textfile2")" >>"$outputfile"
Assuming you want to read from a stream that consists of textfile1 and textfile2 concatenated (rather than from a file with a name that consists of those), this should be:
# PRESUMABLY CORRECT:
# Read from a stream with the contents of textfile1 and then textfile2
done < <(cat -- "$textfile1" "$textfile2") >>"$outputfile"

for loop on files that don't exist [duplicate]

This question already has answers here:
How to skip the for loop when there are no matching files?
(2 answers)
Closed 3 years ago.
I want to process a set of files (*.ui) in the current directory. The following script works as expected if some *.ui files are found. But if no .ui file exist the current directory, the for loop is entered all the same. Why is that ?
for f in *.ui
do
echo "Processing $f..."
done
It prints :
Processing *.ui...
Use:
shopt -s nullglob
From man bash:
nullglob
If set, bash allows patterns which match no files (see Pathname Expansion
above) to expand to a null string, rather than themselves.
You already have the how, the 'why' is that bash will first try to match *.ui to files, but if that doesn't work (it gets no results) it will assume you meant the string "*.ui".
for f in "*.ui"
do
echo "Processing $f..."
done
wil indeed print "Processing *.ui".

Resources