How to loop over files in directory and change path and add suffix to filename How to loop over files in directory and change path and add suffix to filename bash bash

How to loop over files in directory and change path and add suffix to filename


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/bashfor filename in /Data/*.txt; do    for ((i=0; i<=3; i++)); do        ./MyProgram.exe "$filename" "Logs/$(basename "$filename" .txt)_Log$i.txt"    donedone

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.


Sorry for necromancing the thread, but whenever you iterate over files by globbing, it's good practice to avoid the corner case where the glob does not match (which makes the loop variable expand to the (un-matching) glob pattern string itself).

For example:

for filename in Data/*.txt; do    [ -e "$filename" ] || continue    # ... rest of the loop bodydone

Reference: Bash Pitfalls


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

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.