编写可接收命令行参数的Bash脚本统计目录文件数量
Fixing Your Bash Script to Count Files in a Directory
Hey there! Let's break down what's wrong with your current approach and build a reliable script that does exactly what you need.
What's Wrong with Your Original Command?
Your ls /$@/ | wc -l has a couple of key issues:
- Incorrect path formatting:
/$@/adds unnecessary slashes around your directory argument. If you pass an absolute path like/home/my_project, this becomes///home/my_project/— while some shells might tolerate this, it's messy and error-prone. Since you only need one directory parameter, use"$1"(the first command-line argument) instead of$@(which refers to all parameters). - Unreliable counting:
ls | wc -lcounts all entries in the directory, including subdirectories, not just regular files. Even worse, if any filename contains a newline character (yes, that's allowed in Unix!),lswill split it into multiple lines, makingwc -lreturn an incorrect count.
Reliable Script Solutions
Here are two robust approaches to get the job done right:
Option 1: Use find (Most Reliable)
This method handles all edge cases, including weird filenames, and explicitly counts only regular files (not directories, symlinks, or special files):
#!/bin/bash # Check if exactly one directory argument is provided if [ $# -ne 1 ]; then echo "Usage: $0 <directory>" exit 1 fi TARGET_DIR="$1" # Verify the directory exists if [ ! -d "$TARGET_DIR" ]; then echo "Error: '$TARGET_DIR' is not a valid directory." exit 1 fi # Count regular files (non-recursive, only current directory) file_count=$(find "$TARGET_DIR" -maxdepth 1 -type f | wc -l) echo "$TARGET_DIR has $file_count files"
-maxdepth 1: Ensures we don't count files in subdirectories (remove this if you want recursive counting).-type f: Filters only regular files, excluding directories, symlinks, and other special file types.
Option 2: Use Shell Globbing (Faster for Simple Cases)
If you're working with a directory that doesn't have filenames with newlines, this approach is more lightweight:
#!/bin/bash if [ $# -ne 1 ]; then echo "Usage: $0 <directory>" exit 1 fi TARGET_DIR="$1" if [ ! -d "$TARGET_DIR" ]; then echo "Error: '$TARGET_DIR' is not a valid directory." exit 1 fi # Enable nullglob to handle empty directories properly shopt -s nullglob # Collect all entries in the directory all_entries=("$TARGET_DIR"/*) file_count=0 # Loop through entries and count only regular files for entry in "${all_entries[@]}"; do if [ -f "$entry" ]; then ((file_count++)) fi done # Disable nullglob (optional, but clean) shopt -u nullglob echo "$TARGET_DIR has $file_count files"
shopt -s nullglob: Makes the glob return an empty list if the directory has no files, instead of the literal string$TARGET_DIR/*(which would mess up the count).
How to Use the Script
- Save either script to a file (e.g.,
count_files.sh). - Make it executable:
chmod +x count_files.sh. - Run it with your target directory:
./count_files.sh my_project
You'll get output exactly like you wanted: my_project has 3 files
内容的提问来源于stack exchange,提问作者user16068074
相关产品推荐
相关产品推荐

