bash directories - How to iterate over files in a directory with Bash?




3 Answers

A couple of notes first: when you use Data/data1.txt as an argument, should it really be /Data/data1.txt (with a leading slash)? Also, should the outer loop scan only for .txt files, or all files in /Data? Here's an answer, assuming /Data/data1.txt and .txt files only:

#!/bin/bash
for filename in /Data/*.txt; do
    for ((i=0; i<=3; i++)); do
        ./MyProgram.exe "$filename" "Logs/$(basename "$filename" .txt)_Log$i.txt"
    done
done

Notes:

  • /Data/*.txt expands to the paths of the text files in /Data (including the /Data/ part)
  • $( ... ) runs a shell command and inserts its output at that point in the command line
  • basename somepath .txt outputs the base part of somepath, with .txt removed from the end (e.g. /Data/file.txt -> file)

If you needed to run MyProgram with Data/file.txt instead of /Data/file.txt, use "${filename#/}" to remove the leading slash. On the other hand, if it's really Data not /Data you want to scan, just use for filename in Data/*.txt.

and for

I need to write a script that starts my program with different arguments, but I'm new to Bash. I start my program like this:

./MyProgram.exe Data/data1.txt [Logs/data1_Log.txt].

Here is the pseudocode for what i want to do:

for each filename in /Data do
  for int i = 0, i = 3, i++
    ./MyProgram.exe Data/filename.txt Logs/filename_Log{i}.txt
  end if
end for

So I'm really puzzled how to create second argument from the first one, so it looks like dataABCD_Log1.txt and start my program. Help is very much appreciated.

P.S. I know there are simililar questions out there, but I found nothing on creating my logfile name.




for file in Data/*.txt
do
    for ((i = 0; i < 3; i++))
    do
        name=${file##*/}
        base=${name%.txt}
        ./MyProgram.exe "$file" Logs/"${base}_Log$i.txt"
    done
done

The name=${file##*/} substitution (shell parameter expansion) removes the leading pathname up to the last /.

The base=${name%.txt} substitution removes the trailing .txt. It's a bit trickier if the extensions can vary.




Looks like you're trying to execute a windows file (.exe) Surely you ought to be using powershell. Anyway on a Linux bash shell a simple one-liner will suffice.

[/home/$] for filename in `ls /Data/*.txt`; do for i in {0..3}; do ./MyProgam.exe Data/filename Logs/$filename_log$i.txt; done done

Or in a bash

#!/bin/bash

for filename in `ls /Data/*.txt`; 
   do
     for i in {0..3}; 
       do ./MyProgam.exe Data/filename.txt Logs/$filename_log$i.txt; 
     done 
 done



Related

bash for-loop filenames