Skip to main content

Command Palette

Search for a command to run...

Convert Hundreds of Files in Seconds? Your Complete Guide to Bash Shell Script For Loops

Stop Converting Files One by One — Let a 10-Line Script Do It for You

Updated
5 min read
Convert Hundreds of Files in Seconds? Your Complete Guide to Bash Shell Script For Loops

Imagine this: your boss just dropped 50 meeting recordings in your inbox. They're all .m4a files, but the transcription tool you're using only accepts .wav. One by one, you open the converter, drag the file in, hit save, wait... and repeat.

That's an hour of your life you're never getting back.

But what if you could build your own assembly line? A conveyor belt that you simply dump all the files onto — and it processes every single one automatically while you grab a coffee.

That's exactly what we're building today.

Single Learning Objective: Master the Bash for loop to apply the same operation to every file in a folder — all at once.


1. The Magic Spell: The Full Script at a Glance

Here's the complete script we'll be working with. It finds every .m4a file in a folder and converts it to a high-quality .wav file automatically.

#!/bin/bash

for file in *.m4a; do
    [ -e "$file" ] || continue
    
    echo "Processing: $file"
    
    # Extract filename without extension
    filename="${file%.*}"
    
    # Run the conversion
    ffmpeg -i "\(file" -ar 16000 -ac 1 -c:a pcm_s16le "\){filename}.wav"
done

echo "All conversions complete!"

Looks a bit cryptic? Don't worry — let's break it down piece by piece using our assembly line analogy.


2. Dissecting the Code: 4 Simple Steps

for file in *.m4a; do — Starting the Conveyor Belt

This is the heart of the whole operation. *.m4a means "every file in this folder that ends in .m4a." The loop picks them up one by one, slaps a name tag called file on each, and runs everything between do and done for every single one.

[ -e "$file" ] || continue — Filtering Out Empty Boxes

What if there are no .m4a files in the folder at all? Without this line, your script would throw an error trying to process thin air. This guard clause says: "If the file doesn't actually exist, skip it and move on." It's a small line that saves a lot of headaches.

filename="${file%.*}" — Making a New Label

If the input is interview.m4a, we want the output to be interview.wav. The ${file%.*} syntax acts like a pair of scissors — it trims everything from the dot to the end of the filename. What's left in filename is just the clean name: interview.

ffmpeg -i "$file" ... — Running the Machine

Now we feed the prepared material into the converter:

  • -i "$file" feeds in the original file as input

  • -ar 16000 -ac 1 sets the sample rate to 16kHz and converts to mono — standard settings for speech-to-text tools

  • "${filename}.wav" attaches .wav to the clean name we extracted, producing the final output file

Everything between do and done repeats for every file. 100 files? The machine runs 100 times, then stops.


3. 🚀 Run It Right Now: Your Step-by-Step Action Plan

Reading about code is good. Running it is better. Here's how to test this on your own machine today:

  • Step 1: Create a test folder and drop a few .m4a audio files inside.

  • Step 2: Open a text editor, create a new file called convert.sh, paste the script, and save it.

  • Step 3: Open your terminal, navigate to the folder, and give the script permission to run:

    chmod +x convert.sh
    
  • Step 4: Run it and watch the magic happen:

    ./convert.sh
    

💡 Getting a ffmpeg: command not found error? You just need to install ffmpeg first. On Mac, run brew install ffmpeg. On Ubuntu/Debian, use sudo apt install ffmpeg.


4. Swap the Machine, Keep the Belt

The real power of the for loop isn't the audio conversion — it's the structure. The conveyor belt stays the same. You just swap out the machine in the middle to automate almost any repetitive file task imaginable.

Here are a few ready-to-use examples:


💡 Example 1: Bulk-Rename Files with a Prefix

(Add "2024_" to the front of every PDF report at once)

for file in *.pdf; do
    mv "\(file" "2024_\)file"
done

💡 Example 2: Batch-Resize All Images in a Folder

(Shrink hundreds of .jpg files down to 800px wide — Mac/Linux)

for file in *.jpg; do
    sips -Z 800 "$file"
done

💡 Example 3: Merge Multiple Text Files into One

(Combine monthly log files or split data chunks into a single file)

for file in *.txt; do
    cat "$file" >> all_logs_combined.txt
done

Once you internalize the structure of the for loop, you'll start seeing repetitive tasks everywhere — and you'll know exactly how to kill them.


What Repetitive Task Would You Put on the Conveyor Belt?

Think about the last time you did the same thing to 20 files in a row. That's your next automation candidate.

Drop a comment below and let me know what tedious task you're dealing with. I'll cover it in an upcoming post — and help you never do it manually again.


Found this useful? Share it with a colleague who's still converting files one by one. 🙏