如何批量创建目录并按标识符批量移动文件?脚本实现求助
Got it, let's work through this problem together. You want to auto-create directories based on an identifier extracted from each file's name (specifically the "first column" of the filename), then move all files with the same identifier into their matching directory. Here's a solid, safe implementation using a bash script, with explanations for each step.
Assumptions First
Let's clarify what "first column" means—we'll assume your filenames use a consistent delimiter (like _, -, or even spaces) to split the identifier from the rest of the name. For example:
customer_XYZ_invoice.pdf→ identifier iscustomer(split by_)ProjectA - draft.docx→ identifier isProjectA(split by space)2024_report_q1.csv→ identifier is2024(split by_)
If your delimiter is different, just adjust the script below accordingly.
Complete Bash Script
#!/bin/bash # Set your target directory (use "." for current directory) TARGET_DIR="./" # Loop through all items in the target directory for item in "$TARGET_DIR"/*; do # Skip directories—only process files if [ ! -f "$item" ]; then continue fi # Get just the filename (remove the path) filename=$(basename "$item") # Split the filename into "identifier" and the rest using your delimiter # Replace "_" with your actual delimiter (e.g., "-", " ") IFS='_' read -r identifier unused_part <<< "$filename" # Create the directory if it doesn't exist (mkdir -p avoids errors if it already exists) if [ ! -d "$TARGET_DIR/$identifier" ]; then mkdir -p "$TARGET_DIR/$identifier" echo "Created directory: $identifier" fi # Move the file into the matching directory mv "$item" "$TARGET_DIR/$identifier/" echo "Moved: $filename → $identifier/" done
Key Script Explanations
[ ! -f "$item" ] || continue: Ensures we only work with files, not existing subdirectories.basename "$item": Strips the path from the file, so we're only working with the actual filename (critical if your target directory isn't the current one).IFS='_' read -r identifier ...: This is the core part that extracts your identifier.IFSsets the delimiter, andreadsplits the filename into the first segment (your identifier) and the rest.mkdir -p: The-pflag makes sure the directory is created even if parent directories don't exist, and it won't throw an error if the directory already exists.- Quoted variables (
"$item","$filename"): Handles filenames with spaces, special characters (like&,$), or weird punctuation—super important for avoiding bugs!
Customization Tips
- Different delimiter? Change
IFS='_'to your delimiter:- For spaces:
IFS=' ' read -r identifier ... - For hyphens:
IFS='-' read -r identifier ...
- For spaces:
- Identifier is fixed-length? If your identifier is, say, the first 4 characters of the filename (e.g.,
2024from2024_05_report.pdf), replace the split line with:identifier=${filename:0:4} - Test first! Always run this script on a copy of your files first to make sure it behaves as expected. You don't want to accidentally move important files incorrectly.
Final Notes
This script is lightweight, portable (works on any Unix-like system with bash), and handles edge cases like spaces in filenames. If you need to adjust it for a specific filename pattern, just tweak the identifier extraction part.
内容的提问来源于stack exchange,提问作者Trailing Penguin

