19

Let me first describe my situation, I am working on a Linux platform and have a collection of .bmp files that add one to the picture number from filename0022.bmp up to filename0680.bmp. So a total of 658 pictures. I want to be able to run each of these pictures through a .exe file that operates on the picture then kicks out the file to a file specified by the user, it also has some threshold arguments: lower, upper. So the typical call for the executable is:

./filter inputfile outputfile lower upper

Is there a way that I can loop this call over all the files just from the terminal or by creating some kind of bash script? My problem is similar to this: Execute a command over multiple files with a batch file but this time I am working in a Linux command line terminal.

6 Answers 6

17

You may be interested in looking into bash scripting.

You can execute commands in a for loop directly from the shell.

A simple loop to generate the numbers you specifically mentioned. For example, from the shell:

user@machine $ for i in {22..680} ; do
> echo "filename${i}.bmp"
> done

This will give you a list from filename22.bmp to filename680.bmp. That simply handles the iteration of the range you had mentioned. This doesn't cover zero padding numbers. To do this you can use printf. The printf syntax is printf format argument. We can use the $i variable from our previous loop as the argument and apply the %Wd format where W is the width. Prefixing the W placeholder will specify the character to use. Example:

user@machine $ for i in {22..680} ; do
> echo "filename$(printf '%04d' $i).bmp"
> done

In the above $() acts as a variable, executing commands to obtain the value opposed to a predefined value.

This should now give you the filenames you had specified. We can take that and apply it to the actual application:

user@machine $ for i in {22..680} ; do
> ./filter "filename$(printf '%04d' $i).bmp" lower upper
> done

This can be rewritten to form one line:

user@machine $ for i in {22..680} ; do ./filter "filename$(printf '%04d' $i).bmp" lower upper ; done

One thing to note from the question, .exe files are generally compiled in COFF format where linux expects an ELF format executable.

Sign up to request clarification or add additional context in comments.

1 Comment

the user@machine $ is to simulate a shell prompt, the > simulates the prompt continuation expecting more before completing command for execution.
15

here is a simple example:

for i in {1..100}; do echo "Hello Linux Terminal"; done

to append to a file:(>> is used to append, you can also use > to overwrite)

for i in {1..100}; do echo "Hello Linux Terminal" >> file.txt; done

Comments

8

You can try something like this...

#! /bin/bash
for ((a=022; a <= 658 ; a++))
do
   printf "./filter filename%04d.bmp outputfile lower upper" $a | "sh"
done

5 Comments

here is what I tried and it printed a bunch of somewhat relevant things to my screen but did not actually create any files... #! /bin/bash for ((a=022; a<=680; a++)) do printf "./filter fetus-00-2.3.5um__voi0%04d.bmp fetus_threshold_%04d 90 240" $a done where 90 and 240 are the lower and upper arguments I mentioned earlier. I have not made a bash script so I just used emacs to create a file where I typed the previous lines of code. I then saved the emacs file simply as test. with nothing behind it because that is what I saw a few example do online. Any further tips?
try making it into a .sh file (with the new addition I made above) and then running the file by typing [[bash myfile.sh]] in the same directory
Well, good news...it at least iterates this time around and it even works on the first image, then I get some errors coming from the software the executable is using. The thing I am not understanding is that it is trying to start at inputfile0000 and we tell it to start with inputfile0022.bmp. The only output image I am getting is outputfile0000.bmp. Here is the bash file I saved as threshold.sh: #! /bin/bash for ((a=022; a<= 680; a++)) do printf "./filter6 fetus-00-2_3.5um__rec_voi%04d.bmp fetus_threshold_%04d.bmp 90 240" $a | "sh" done
I am not sure what is up but I see one issue...for each reference in the printf statement you will need to give an argument (i.e. you should have $a $a rather than just one.
Ye Haw!!! That did the trick!!! It still tries to start at input0000.bmp for some reason despite setting a=22 but I can do a simple bit of code to alter the name of the files to start at 0 if I get tired of throwing 21 exceptions. Thank you for your help.
2

You can leverage xargs for iterating:

ls | xargs -i ./filter {} {}_out lower upper

Note:

  • {} corresponds to one line output from the pipe, here it's the inputfile name.
  • Output files wouldbe named with postfix '_out'.

Comments

1

You can test that AS-IS in your shell :

for i in *; do
    echo "$i" | tr '[:lower:]' '[:upper:]'
done

If you have a special path, change * by your path + a glob : Ex :

for i in /home/me/*.exe; do ...

See http://mywiki.wooledge.org/glob

3 Comments

Edited to explain this possibility =)
hey sputnick, Could you help me understand the bit of code you wrote above? I can see you have a for loop going over everything but do not see where you ever call the executable to process the images. Could you give me a bit more detail and explanation? Thank you for your help and posts. It great to get this much help in such a short time.
@user1452373 I believe he was giving a general example on executing a for loop directly from the shell to show what it would do opposed to actually executing. I feel it's a good practice to test any file operations that involve a loop prior to executing them.
0

This while prepend the name of the output images like filtered_filename0055.bmp

for i in *; do
    ./filter $i filtered_$i lower upper
done

4 Comments

This will overwrite the source file I guess.
What if a file has a space in it? Then the command will resolve to ./filter file withspace filtered_file withspace lower upper. You should probably quote "$i" when you're using it.
@TimPote Just trying to make it as simple as possible based on the question info., but yes quotes will make it better also some checking for file extension and directory.
If one of the files captured by the glob pattern contains a space, the number of arguments passed to ./filter would shift.

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.