Build a File Organizer with Bash
Write a bash script that sorts files into folders by type automatically.
Introduction
30 Second Summary
Everyone has had that moment where their Downloads folder is an overwhelming mess of random files. Finding the one document you need means scrolling past photos, music, videos, and code files all jumbled together.
In this project, you will write a Bash script that automatically sorts a messy folder of files into organized subfolders by type. You will learn terminal navigation, scripting fundamentals, and how to build a practical automation tool from scratch.
What You'll Build
You run a single command on any cluttered folder, and every file sorts itself into the right subfolder while a log records exactly what happened.
By the end of this project, you'll have:
- A working file organizer script called organizer.sh that sorts a dozen jumbled files into labeled subfolders like Documents, Images, and Code in seconds.
- A timestamped log in organizer-log.txt that records every file move, so you always know exactly what changed and where it went.
- Error handling and script arguments that let you point the organizer at any folder path and get clear feedback if something goes wrong.
- Secret Mission: Add a --dry-run mode that previews what the script would do without actually moving anything.
Are there any prerequisites?
None. This project includes setup instructions for every tool you need. No prior command line experience is required.
Before We Start
Before we dive in, let's lock in what you're about to build and why it matters.
Set Up Your Bash Environment
Every command you type and every script you write in this project starts in a terminal. Bash is a command-line shell that lets you interact with your computer by typing text commands instead of clicking buttons.
On macOS and Linux, Bash comes pre-installed. On Windows, you'll install WSL (Windows Subsystem for Linux) to get a full Linux environment with Bash included.
In this step, get ready to:
- Open a terminal on your platform.
- Confirm Bash is installed and running.
Open a terminal
The setup is slightly different depending on your operating system. Find your platform below and follow the instructions.
macOS
macOS uses zsh as its default shell. You need to switch to Bash for this project.
- Press Cmd+Space to open Spotlight search.
- Type Terminal and press Enter to open it.
- Switch to a Bash shell by running this command:
bash
You may notice your terminal prompt change slightly. This is normal and means you've switched from zsh to Bash.
Windows
Windows doesn't include Bash by default. You'll install WSL to get a full Linux environment.
- Press the Windows key to open your search bar.
- Type PowerShell.
- Right-click on Windows PowerShell and select Run as administrator.
- Install WSL by running this command:
wsl --install
What does this command do?
wsl --install installs WSL with Ubuntu as the default Linux distribution. It also enables the components Windows needs to run Linux programs.
This requires Windows 10 version 2004 or later (Build 19041), or Windows 11. The installation may take several minutes.
- Restart your computer when the installation finishes.
- After restarting, press the Windows key to open your search bar.
- Type Ubuntu and press Enter to open it.
Setting up your Linux username and password
Ubuntu will display "Installing, this may take a few minutes..." on its first launch. Once that finishes, it will ask you to create a Linux username and password.
When you type your password, no characters appear on the screen. This is normal Linux security behavior. Type your password and press Enter even though the screen looks blank.
- Type a username and press Enter.
- Type a password and press Enter.
- Retype the same password to confirm and press Enter.
Seeing an error during installation?
- Make sure you opened PowerShell as an administrator, not as a regular user. Right-click and select Run as administrator.
- Check that your Windows version is 2004 (Build 19041) or later. You can check in Settings, then System, then About.
- If you see a message about virtualization, you may need to enable it in your BIOS settings. Search online for your computer model and "enable virtualization."
Help me troubleshoot my WSL installation on Windows.
Linux
Most Linux distributions use Bash as the default shell, so minimal setup is needed.
- Press the Super key or open your application menu.
- Search for Terminal and open your terminal emulator.
You should already be in a Bash shell and ready to continue.
Verify bash is working
No matter which platform you're on, this next check is the same. What do you think you'll see when you check which version of Bash is running?
- Find out by running this command:
bash --version
✔️ I see version information
You should see output starting with GNU bash, version followed by a version number.
On Linux and WSL, you'll typically see version 5.x. On macOS, you'll see version 3.2. Both work perfectly for this project.
ⓧ Command not found
This usually means Bash is not set up correctly on your machine. Try the fix for your platform.
- Windows: Make sure you are running the command inside the Ubuntu terminal, not PowerShell. Close PowerShell and open Ubuntu from the Start menu.
- macOS: Run bash first to switch from zsh, then try the version check again.
- Linux: Bash may not be installed on your distribution. Use your package manager to install it.
Why is Bash not working on my machine?
Your terminal is ready and Bash is running. Next up, you'll navigate the filesystem, create folders, and build the test files your script will organize.
Navigate the Terminal and Create Your Test Files
Your bash environment is ready to go. Now it's time to get your hands dirty with some real terminal commands.
Before you can automate file sorting, you need to know how to move around the filesystem and create files by hand. This step builds the muscle memory for every command your script will use later.
In this step, get ready to:
- Navigate directories with pwd, ls, cd, and mkdir.
- Create 12 test files using touch and echo.
- Inspect files and their details with cat and ls -l.
Navigate the filesystem
Every terminal session drops you into a folder on your computer. Your first job is to figure out where you are, what's around you, and how to move.
- See which folder you are currently in by running this command:
pwd
You should see a path printed, something like /home/username on Linux/WSL or /Users/username on macOS. This is your current directory.
What does pwd mean?
pwd stands for print working directory. It shows the full path of the folder you are currently inside. Think of it as asking the terminal "where am I right now?"
- See what's inside your current directory by running:
ls
You should see a list of files and folders. It might be empty if this is a fresh environment, and that's perfectly fine.
- Create a new folder called messy-folder by running:
mkdir messy-folder
- Confirm the folder was created by running:
ls
You should see messy-folder listed in the output.
What do ls and mkdir do?
ls stands for list. It shows everything inside the current directory.
mkdir stands for make directory. It creates a new folder with the name you give it.
- Move into the messy-folder directory by running:
cd messy-folder
- Confirm you moved inside the folder by running:
pwd
You should now see messy-folder at the end of your path, confirming you're inside it.
- Move back out to the parent directory by running:
cd ..
What does cd do?
cd stands for change directory. You give it a folder name and it moves you there. The special shortcut .. means "one level up," so cd .. takes you back to the folder that contains your current one.
Seeing 'No such file or directory'?
This usually means a typo in the folder name. Run ls to see what folders exist, then make sure you spell the name exactly as shown.
help me fix a 'No such file or directory' error when using cd
Create your test files
Your organizer script needs a messy folder full of mixed file types to sort. You'll create 12 dummy files that mimic a real cluttered folder with documents, images, audio, videos, and code files.
- Create three text files inside messy-folder by running:
touch messy-folder/report.txt messy-folder/notes.txt messy-folder/todo.txt
- Create three image files by running:
touch messy-folder/photo.jpg messy-folder/logo.png messy-folder/banner.gif
- Confirm your first six files exist by running:
ls messy-folder
You should see six files listed: banner.gif, logo.png, notes.txt, photo.jpg, report.txt, and todo.txt.
What does touch do?
touch creates an empty file with the name you give it. You can list multiple file names after touch to create several files at once.
The files are empty right now. The extensions (.txt, .jpg, .png) are just part of the file name. They tell your organizer script what type each file is.
- Create two audio files by running:
touch messy-folder/song.mp3 messy-folder/podcast.wav
- Create two video files by running:
touch messy-folder/movie.mp4 messy-folder/clip.mov
- Confirm the folder is growing by running:
ls messy-folder
You should now see ten files listed.
- Create the last two files, both code files, by running:
touch messy-folder/app.js messy-folder/style.css
- Write some content into report.txt by running:
echo "This is my report" > messy-folder/report.txt
What does the > symbol do?
echo prints text to the screen. The > symbol redirects that output into a file instead of displaying it. So echo "This is my report" > report.txt writes the text into report.txt.
Inspect your files
Time to verify everything landed correctly. You'll use three different commands to look at your folder from different angles.
- Before you run the next command, think about how many files you expect to see in messy-folder. What types of files should be there?
- List all 12 files by running:
ls messy-folder
You should see all 12 files: app.js, banner.gif, clip.mov, logo.png, movie.mp4, notes.txt, photo.jpg, podcast.wav, report.txt, song.mp3, style.css, and todo.txt.
- See more details about each file by running:
ls -l messy-folder
This time the output shows extra information for each file, including its size and the date it was created. Most files show a size of 0 because touch creates empty files.
What does the -l flag do?
The -l flag stands for long format. Flags are options you pass to a command to change its behavior. Without -l, ls just shows file names. With -l, it shows permissions, owner, size, and modification date.
- Read the content you wrote into report.txt by running:
cat messy-folder/report.txt
You should see This is my report printed to the terminal. That confirms the echo and > redirect worked correctly.
What does cat do?
cat stands for concatenate. Its original purpose is to join files together, but its most common use is to quickly display the contents of a file in the terminal.
Not seeing 12 files?
Make sure you ran all five touch commands from the previous substep. If a file is missing, re-run the touch command for that group.
Check that you are running ls messy-folder from the parent directory, not from inside messy-folder itself. Run pwd to see where you are.
help me figure out why I'm not seeing all 12 files in messy-folder
Nice work building up your file collection. You've got 12 files of all different types sitting in one cluttered folder. In the next step, you'll write a script that starts sorting these files automatically.
Write Your First Bash Script
Your messy-folder is stocked with 12 test files ready to sort. Typing individual mv commands to move each one would work, but imagine doing that for hundreds of files.
A bash script saves a sequence of commands in a file so you can replay them with a single command. In this step, you'll write your first script to start organizing those files automatically.
In this step, get ready to:
- Create your first bash script using the nano text editor.
- Run the script and see files get organized.
Create the organizer script in nano
nano is a text editor that runs right inside your terminal. Instead of opening a separate window, it turns your terminal into an editor where you can type and save code.
- Create and open a new file called organizer.sh by running this command:
nano organizer.sh
What will I see?
Your terminal transforms into a text editor with a blank area for typing and shortcut hints at the bottom. The ^ symbol in those hints means the Ctrl key.
- Type the following code into nano exactly as shown:
#!/bin/bash
# Set the folder to organize
SOURCE_DIR="messy-folder"
# Create a Documents subfolder (-p means no error if it exists)
mkdir -p "$SOURCE_DIR/Documents"
# Loop through every .txt file in the source folder
for file in "$SOURCE_DIR"/*.txt; do
if [ -f "$file" ]; then
# Extract just the filename from the full path
filename=$(basename "$file")
# Move the file into Documents
mv "$file" "$SOURCE_DIR/Documents/"
echo "Moved: $filename -> Documents/"
fi
done
What does this code do?
- #!/bin/bash is called a shebang. It tells your system to run this file using bash.
- SOURCE_DIR="messy-folder" stores the folder name in a variable so you can reuse it throughout the script without retyping it.
- mkdir -p creates the Documents subfolder. The -p flag means it won't throw an error if the folder already exists.
- The for loop grabs every .txt file in the folder, extracts its name with basename, moves it into Documents/, and prints a message confirming the move.
- Save the file by pressing Ctrl+O (that's the letter O, not zero).
- Press Enter to confirm the filename.
- Exit nano by pressing Ctrl+X.
You're back at your normal terminal prompt. The file organizer.sh is now saved in your current directory.
- Confirm the file was created by running:
ls organizer.sh
You should see organizer.sh printed in the output.
Don't see organizer.sh?
- Make sure you pressed Ctrl+O and then Enter to save before exiting. If you only pressed Ctrl+X, nano may have exited without saving.
- Run nano organizer.sh again and re-enter the code, then save with Ctrl+O, Enter, Ctrl+X.
Help me figure out why my file wasn't saved in nano.
Make the script executable and run it
By default, a new file is just text. Your system won't let you run it as a program until you explicitly mark it as executable.
- Make organizer.sh executable by running this command:
chmod +x organizer.sh
What does chmod +x do?
chmod changes file permissions. The +x flag adds "execute" permission, which tells your system this file is allowed to run as a program.
Before you run the script, think about what you expect to happen. Look back at the code you wrote. Which files in messy-folder do you think will move, and which ones will stay put?
- Run your script by running this command:
./organizer.sh
You should see three lines printed in your terminal:
Moved: notes.txt -> Documents/
Moved: report.txt -> Documents/
Moved: todo.txt -> Documents/
Seeing Permission denied?
- Make sure you ran chmod +x organizer.sh before trying to run the script.
- Check that you're running the script with ./organizer.sh (with the ./ prefix), not just organizer.sh.
Help me fix a permission error when running my bash script.
- Verify the .txt files moved into Documents by running:
ls messy-folder/Documents/
You should see notes.txt, report.txt, and todo.txt listed there.
- Now check what is left in the main folder by running:
ls messy-folder
You should see the Documents subfolder plus 9 files still sitting loose: app.js, banner.gif, clip.mov, logo.png, movie.mp4, photo.jpg, podcast.wav, song.mp3, and style.css.
Why are 9 files still there?
This is exactly what should happen. Your script's for loop only targets *.txt files, so images, audio, video, and code files are completely ignored.
Three files sorted, nine left behind. That gap is the problem you'll solve in the next step.
✔️ Awesome, I've got everything!
Great. Double check you've saved organizer.sh and that the three .txt files are inside messy-folder/Documents/.
ⓧ I'd like to double check the full code
Open your script by running cat organizer.sh and compare it to the code below. The comments are optional, but all other lines should match.
#!/bin/bash
SOURCE_DIR="messy-folder"
mkdir -p "$SOURCE_DIR/Documents"
for file in "$SOURCE_DIR"/*.txt; do
if [ -f "$file" ]; then
filename=$(basename "$file")
mv "$file" "$SOURCE_DIR/Documents/"
echo "Moved: $filename -> Documents/"
fi
done
Your first bash script works. It moved the text files exactly where you told it to. But 9 files are still sitting in the mess. Next up, you'll add a function with a case statement that knows how to sort every file type in one sweep.
Sort All File Types with a Function and Case Statement
In the last step, you ran your script and watched it move the three .txt files into a Documents folder. That felt great. But 9 files are still sitting loose in messy-folder, completely untouched.
The problem is that the script only knows about one file type. To handle images, audio, video, and code files, you need a way to look at any file extension and decide where it belongs. In this step, you will write a function with a case statement that categorizes every file type so one run cleans up the entire mess.
In this step, get ready to:
- Reset your test folder with a fresh set of 12 files.
- Write a function with a case statement to categorize files by extension.
- Run the script and verify every file is sorted into the correct subfolder.
Reset your test folder
Your messy-folder currently has three .txt files already sorted into Documents/. To test the new script properly, you need a clean slate with all 12 files back in the root of the folder.
- Delete messy-folder and recreate it with all 12 original files by running these commands:
rm -r messy-folder
mkdir messy-folder
touch messy-folder/report.txt messy-folder/notes.txt messy-folder/todo.txt
touch messy-folder/photo.jpg messy-folder/logo.png messy-folder/banner.gif
touch messy-folder/song.mp3 messy-folder/podcast.wav
touch messy-folder/movie.mp4 messy-folder/clip.mov
touch messy-folder/app.js messy-folder/style.css
echo "This is my report" > messy-folder/report.txt
- Confirm all 12 files are back by running:
ls messy-folder
You should see all 12 files listed: app.js, banner.gif, clip.mov, logo.png, movie.mp4, notes.txt, photo.jpg, podcast.wav, report.txt, song.mp3, style.css, and todo.txt. No subfolders this time.
Seeing a "No such file or directory" error?
Make sure you are in the same directory where messy-folder lives. Run pwd to check your current directory, then cd to the right location if needed.
Why can't I reset my test folder?
Write the get_category function
The old script hardcoded a single file type. Instead, you will write a function called get_category that accepts any file extension and returns the right category name. A case statement inside the function checks the extension against a set of patterns.
- Open organizer.sh in nano by running:
nano organizer.sh
- Delete all the existing content by pressing Ctrl+K repeatedly until the file is empty.
- Type the following code to set up the shebang line, the source directory variable, and the get_category function:
#!/bin/bash
SOURCE_DIR="messy-folder"
# Determine which category a file belongs to based on extension
get_category() {
local extension
extension=$(echo "$1" | tr '[:upper:]' '[:lower:]')
case "$extension" in
txt|doc|pdf|docx)
echo "Documents"
;;
jpg|jpeg|png|gif|svg)
echo "Images"
;;
mp3|wav|flac|aac)
echo "Audio"
;;
mp4|mov|avi|mkv)
echo "Videos"
;;
sh|py|js|html|css)
echo "Code"
;;
*)
echo "Other"
;;
esac
}
What does this function do?
- get_category() is a function that takes one argument (a file extension) and prints a category name.
- local extension creates a variable that only exists inside this function, so it does not accidentally overwrite anything outside.
- tr '[:upper:]' '[:lower:]' converts the extension to lowercase so that .JPG and .jpg both match the same pattern.
- The case statement works like a series of "if this matches, do that" checks. The | pipe character means "or", so txt|doc|pdf|docx matches any of those four extensions.
- *) is the catch-all. Any extension that does not match a specific category falls into "Other".
- Leave a blank line after the closing } of the function, then type the main loop that processes every file in the folder:
# Process each file in the source directory
for file in "$SOURCE_DIR"/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
# Extract the file extension
extension="${filename##*.}"
# Handle files without an extension
if [ "$filename" = "$extension" ]; then
category="Other"
else
category=$(get_category "$extension")
fi
mkdir -p "$SOURCE_DIR/$category"
mv "$file" "$SOURCE_DIR/$category/"
echo "Moved: $filename -> $category/"
fi
done
What does this loop do?
- for file in "$SOURCE_DIR"/* loops over everything inside messy-folder. The old loop only matched *.txt. Now * matches all files.
- ${filename##*.} strips everything up to and including the last dot, leaving just the extension. For photo.jpg, it gives you jpg.
- The if [ "$filename" = "$extension" ] check catches files that have no extension at all. If the filename and extension are identical, there was no dot to strip.
- mkdir -p creates the category subfolder only if it does not already exist. Then mv moves the file into it.
- Save the file by pressing Ctrl+O, then press Enter to confirm the filename.
- Exit nano by pressing Ctrl+X.
Run the script and verify all files are sorted
Before you run the script, think about what you expect to happen. Last time, only 3 files moved. What do you think will happen now that the script handles every file type?
- Run the updated script by running:
./organizer.sh
You should see 12 "Moved" lines in your terminal, one for each file being sorted into its category.
- Confirm that no loose files remain by running:
ls messy-folder
You should see only category subfolders listed: Audio, Code, Documents, Images, and Videos. No loose files remaining.
- Spot-check a specific category to make sure the right files landed there by running:
ls messy-folder/Images
You should see banner.gif, logo.png, and photo.jpg.
Files not moving or landing in the wrong folder?
- Check that the case patterns use the pipe character | between extensions (not commas or spaces). For example: txt|doc|pdf|docx.
- Make sure each pattern ends with a closing parenthesis ) and each block ends with double semicolons ;;. Missing either one causes syntax errors.
- Confirm the for loop uses "$SOURCE_DIR"/* (with the asterisk, no file extension filter). If it still says *.txt, only text files will match.
Help me debug my organizer script
✔️ Awesome, I've got everything!
Great. Make sure you have saved organizer.sh and that running ls messy-folder shows only category subfolders with no loose files.
ⓧ I'd like to double check the full code
Your organizer.sh should contain three sections, in this order. Scroll up and confirm each one is present in your file:
- The shebang line #!/bin/bash and the SOURCE_DIR="messy-folder" variable at the top.
- The get_category() function with a case statement covering six patterns (Documents, Images, Audio, Videos, Code, and the * catch-all for Other).
- The for loop that iterates over "$SOURCE_DIR"/*, extracts the extension with ${filename##*.}, calls get_category, creates the subfolder, and moves the file.
If anything is missing, open nano organizer.sh and add the missing section.
Your script now handles every file type in one run. Next up, you will add error handling, a folder argument, and a log file so the script becomes a real tool you can point at any folder.
Add Logging, Error Handling, and Arguments
In Step 4, you built a script that sorts every file type into the right subfolder. But the script only works on one hardcoded folder called messy-folder. It also leaves no trace of what it did.
If you ran it on an important folder and something went wrong, you'd have no way to track what moved where. In this step, you'll add a folder argument, input validation, and a log file to turn organizer.sh into a real, reusable tool.
In this step, get ready to:
- Accept a folder path as a command-line argument.
- Validate the input directory and handle errors.
- Log every file move to a timestamped log file with a running count.
Accept a folder argument and validate input
Right now, SOURCE_DIR is hardcoded to "messy-folder". That means the script can only ever sort files in that one folder. Bash scripts can accept arguments from the command line, so let's use that to make the script flexible.
- Open organizer.sh in nano by running:
nano organizer.sh
- Find this line near the top of the file:
SOURCE_DIR="messy-folder"
- Replace it with this line:
SOURCE_DIR="${1:-messy-folder}"
What does ${1:-messy-folder} mean?
In bash, $1 refers to the first argument passed to the script. The :- syntax provides a default value. If the learner runs ./organizer.sh my-stuff, then $1 is my-stuff.
If they run ./organizer.sh with no argument, $1 is empty and the default messy-folder kicks in.
Now you need a safety check. If someone passes a folder name that doesn't exist, the script should stop and tell them instead of crashing.
- Add this block directly below the SOURCE_DIR line:
if [ ! -d "$SOURCE_DIR" ]; then
echo "Error: '$SOURCE_DIR' is not a directory."
exit 1
fi
What does this code do?
- [ ! -d "$SOURCE_DIR" ] checks whether the path is NOT a directory. The -d flag tests for a directory, and ! negates it.
- exit 1 stops the script immediately and signals an error. An exit code of 0 means success. Anything else means failure.
- Save the file by pressing Ctrl+O, then press Enter to confirm.
- Exit nano by pressing Ctrl+X.
Time to test the error handling. What do you think will happen if you pass a folder name that doesn't exist?
- Test the validation by running:
./organizer.sh fake-folder
You should see Error: 'fake-folder' is not a directory. printed to the screen. The script stopped before trying to sort anything.
Not seeing the error message?
- Make sure the if block is placed after the SOURCE_DIR line and before the get_category function.
- Check for matching square brackets and quotes. The test uses [ ! -d "$SOURCE_DIR" ] with spaces inside the brackets.
Why isn't my error handling working in organizer.sh?
Add logging and a file counter
The error handling works. Now let's tackle the other gap: the script leaves no record of what it did. You'll use a command called tee to write output to both the screen and a log file at the same time.
- Open organizer.sh in nano again by running:
nano organizer.sh
- Add a LOG_FILE variable on the line directly after SOURCE_DIR:
LOG_FILE="organizer-log.txt"
Next, you'll add a header block that prints information about each run. This goes between the closing fi of your if block and the for loop.
- Find the closing fi of your if block (the one right before the get_category function).
- After the closing brace of the get_category function (the } on its own line), and before the for loop, add this header block:
echo "=== File Organizer ===" | tee "$LOG_FILE"
echo "Source: $SOURCE_DIR" | tee -a "$LOG_FILE"
echo "Date: $(date)" | tee -a "$LOG_FILE"
echo "---" | tee -a "$LOG_FILE"
file_count=0
What does tee do?
The tee command splits output into two streams: one goes to the screen and one goes to a file. Think of it like a T-shaped pipe splitter.
- tee "$LOG_FILE" (without -a) creates or overwrites the log file. This is used only on the first line to start a fresh log.
- tee -a "$LOG_FILE" appends to the existing file instead of overwriting it. Every line after the first uses -a.
- $(date) is command substitution. Bash runs the date command and inserts its output into the string.
Now update the loop body so it logs each move and counts files.
- Inside the for loop, find this line:
echo "Moved: $filename -> $category/"
- Replace it with these two lines:
echo "Moved: $filename -> $category/" | tee -a "$LOG_FILE"
file_count=$((file_count + 1))
What does $((file_count + 1)) do?
Bash uses the $(( )) syntax for arithmetic. file_count=$((file_count + 1)) takes the current value of file_count, adds 1, and stores the result back. This increments with every file that gets moved.
Finally, add a summary block after the loop so the learner sees the total and the log file location.
- Find the done line that closes the for loop.
- Add these lines directly after done:
echo "---" | tee -a "$LOG_FILE"
echo "Total files organized: $file_count" | tee -a "$LOG_FILE"
echo "Log saved to: $LOG_FILE"
Why doesn't the last line use tee?
The echo "Log saved to: $LOG_FILE" line is a message for the person running the script. It tells them where to find the log. Writing that message inside the log itself would be circular, so it only prints to the screen.
- Save the file by pressing Ctrl+O, then press Enter to confirm.
- Exit nano by pressing Ctrl+X.
✔️ Awesome, I've got everything!
Make sure you've saved organizer.sh. The file should now have the argument line, the if block, the header block with tee, the updated loop, and the summary at the end.
ⓧ I'd like to double check the full code
The full organizer.sh file is now over 50 lines, so scroll through your file in nano and confirm each section is present, in this order:
- Line 1: the shebang #!/bin/bash.
- SOURCE_DIR="${1:-messy-folder}" followed by LOG_FILE="organizer-log.txt".
- The if [ ! -d "$SOURCE_DIR" ] block with the error message and exit 1.
- The get_category function with the full case statement (unchanged from Step 4).
- Four echo ... | tee header lines followed by file_count=0.
- The for loop with tee -a on the echo line and file_count=$((file_count + 1)) after each move.
- Three summary lines after done: the separator, the total count, and the log file path.
Reset your test folder and run the full test
Your messy-folder currently has files sorted into subfolders from your last run. You need a fresh set of loose files to properly test the updated script.
- Delete the old folder and recreate it with all 12 test files by running these commands:
rm -r messy-folder
mkdir messy-folder
touch messy-folder/report.txt messy-folder/notes.txt messy-folder/todo.txt
touch messy-folder/photo.jpg messy-folder/logo.png messy-folder/banner.gif
touch messy-folder/song.mp3 messy-folder/podcast.wav
touch messy-folder/movie.mp4 messy-folder/clip.mov
touch messy-folder/app.js messy-folder/style.css
echo "This is my report" > messy-folder/report.txt
- Confirm the files are back by running:
ls messy-folder
You should see all 12 files listed as loose files with no subfolders.
Before you run the updated script, think about what you expect to see differently this time. Will the output look different from your Step 4 runs?
- Run the organizer with the folder argument by running:
./organizer.sh messy-folder
You should see the header block with the date, each file's move printed, and a total at the bottom reading Total files organized: 12.
The script also created a log file. Check it to see the full record.
- View the log file by running:
cat organizer-log.txt
You should see a timestamped header, each of the 12 file moves, and the total count. This is your permanent record of everything the script did.
- Confirm the error handling still works by running:
./organizer.sh fake-folder
You should see Error: 'fake-folder' is not a directory. and nothing else. The script exits before trying to sort anything.
Not seeing the log file or the file count?
- Make sure the first tee line (the header) uses tee "$LOG_FILE" without -a. All other tee lines need -a to append.
- Check that file_count=0 is placed before the for loop, not inside it. Placing it inside would reset the count to 0 on every iteration.
- Make sure the three summary lines come after done, not inside the loop.
My organizer.sh runs but the log file is empty or the count is wrong. Help me fix it.
Your script is now a real, reusable tool. You can point it at any folder, it validates the input, sorts every file, and leaves a permanent log of exactly what happened. Next up, you'll take on a secret mission to add a preview mode.
Secret mission
Add a Dry Run Mode
Running a file-moving script on an important folder is nerve-wracking when you cannot preview what will happen. Your mission: add a --dry-run flag that shows exactly which files would move where, without actually touching anything.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. Decide whether to keep your files for future use or delete them.
Resources you used:
- organizer.sh script file.
- messy-folder/ directory and its organized subfolders.
- organizer-log.txt log file.
Keep everything running
No action needed. Choose this if you plan to keep experimenting with your organizer script or want to reuse it on other folders.
- Your files sit on your local machine with no ongoing costs.
- You can run ./organizer.sh on any new folder whenever you need to sort files.
Pause - I'll come back to this later
Since this is a local project with no running services, there is nothing to pause. Your files stay on disk until you decide to delete them.
- Everything is already "paused" by default. No processes are running and no resources are being consumed.
- When you are ready to pick this up again, open your terminal and navigate back to the folder where you created organizer.sh.
Delete - I don't want to use this again
Remove all project files from your machine. This deletes the script, the test folder, and the log file.
- Open your terminal and navigate to the directory where you created organizer.sh and messy-folder.
- Delete the project files by running this command:
rm -rf messy-folder organizer.sh organizer-log.txt
- Confirm the files are gone by running:
ls
- You should no longer see organizer.sh, messy-folder, or organizer-log.txt in the output.
Nice Work!
Nice Work!
You just built a real automation tool from scratch using nothing but the command line. Your organizer.sh script can take any messy folder and sort every file into tidy subfolders, with a full log of everything it did.
You've learned how to:
- Navigate the terminal with pwd, ls, cd, and mkdir, and create and inspect files with touch, echo, and cat.
- Write a bash script with a get_category function, a for loop, and a case statement to automatically sort files by type into category subfolders.
- Add error handling, command-line arguments, and a logging system with tee to turn your script into a reusable tool you can point at any folder.
- Secret Mission: Added a --dry-run flag so you can preview file moves before committing.
Ready to quiz yourself?