Organize files in a specified folder by classifying them into category directories based on file extension.
/file-organizer [target-dir]
Default target: user's Desktop.
| Category | Extensions |
|---|---|
| ------------- | ----------- |
| Documents | .pdf .doc .docx .xls .xlsx .ppt .pptx .txt .md .csv .rtf .odt .epub .pages .numbers .key |
| Images | .jpg .jpeg .png .gif .bmp .svg .webp .ico .tiff .tif .psd .ai |
| Videos | .mp4 .avi .mkv .mov .wmv .flv .webm .m4v .mpeg .mpg .3gp |
| Music | .mp3 .wav .flac .aac .ogg .wma .m4a .opus .alac |
| Archives | .zip .rar .7z .tar .gz .bz2 .xz .zst .iso .dmg .cab |
| Code | .js .ts .py .java .cpp .c .h .hpp .cs .go .rs .rb .php .swift .kt .scala .html .css .json .xml .yaml .yml .toml .ini .cfg .sh .bat .ps1 .sql .graphql .proto .dockerfile |
| Executables | .exe .msi .dll .app .deb .rpm .apk .dmg |
| Fonts | .ttf .otf .woff .woff2 .eot |
| Others | everything else |
Use the Bash tool to run the organizer. The script pattern:
TARGET_DIR="${1:-$HOME/Desktop}" # default: desktop
# dry-run: pass "--dry-run" as second arg
DRY_RUN=false
if [ "$2" = "--dry-run" ]; then DRY_RUN=true; fi
# Define categories
declare -A CAT_MAP
CAT_MAP[pdf]="Documents"; CAT_MAP[docx]="Documents"; CAT_MAP[doc]="Documents"
CAT_MAP[xlsx]="Documents"; CAT_MAP[pptx]="Documents"; CAT_MAP[txt]="Documents"
CAT_MAP[md]="Documents"; CAT_MAP[csv]="Documents"
CAT_MAP[jpg]="Images"; CAT_MAP[jpeg]="Images"; CAT_MAP[png]="Images"
CAT_MAP[gif]="Images"; CAT_MAP[bmp]="Images"; CAT_MAP[svg]="Images"
CAT_MAP[webp]="Images"; CAT_MAP[ico]="Images"
CAT_MAP[mp4]="Videos"; CAT_MAP[avi]="Videos"; CAT_MAP[mkv]="Videos"
CAT_MAP[mov]="Videos"; CAT_MAP[wmv]="Videos"; CAT_MAP[flv]="Videos"
CAT_MAP[mp3]="Music"; CAT_MAP[wav]="Music"; CAT_MAP[flac]="Music"
CAT_MAP[aac]="Music"; CAT_MAP[ogg]="Music"
CAT_MAP[zip]="Archives"; CAT_MAP[rar]="Archives"; CAT_MAP[7z]="Archives"
CAT_MAP[tar]="Archives"; CAT_MAP[gz]="Archives"; CAT_MAP[bz2]="Archives"
CAT_MAP[js]="Code"; CAT_MAP[ts]="Code"; CAT_MAP[py]="Code"
CAT_MAP[java]="Code"; CAT_MAP[html]="Code"; CAT_MAP[css]="Code"
CAT_MAP[json]="Code"; CAT_MAP[xml]="Code"; CAT_MAP[yaml]="Code"
CAT_MAP[yml]="Code"; CAT_MAP[sh]="Code"; CAT_MAP[bat]="Code"
CAT_MAP[go]="Code"; CAT_MAP[rs]="Code"; CAT_MAP[cpp]="Code"
CAT_MAP[c]="Code"; CAT_MAP[php]="Code"; CAT_MAP[rb]="Code"
CAT_MAP[exe]="Executables"; CAT_MAP[msi]="Executables"
CAT_MAP[dll]="Executables"; CAT_MAP[app]="Executables"
CAT_MAP[ttf]="Fonts"; CAT_MAP[otf]="Fonts"; CAT_MAP[woff]="Fonts"
# ---- script ----
echo "=== File Organizer ==="
echo "Target: $TARGET_DIR"
$DRY_RUN && echo "Mode: DRY RUN (no files will be moved)"
# Find all files (not dirs) directly in target
declare -A COUNTS
TOTAL=0
while IFS= read -r -d '' file; do
rel="${file#$TARGET_DIR/}"
base="$(basename "$rel")"
ext="${base##*.}"
# skip if no extension or hidden file
[ "$ext" = "$base" ] && continue
[[ "$base" == .* ]] && continue
ext_lc=$(echo "$ext" | tr '[:upper:]' '[:lower:]')
cat="${CAT_MAP[$ext_lc]:-Others}"
# count
((COUNTS[$cat]++))
((TOTAL++))
if $DRY_RUN; then
echo " [$cat] $rel"
fi
done < <(find "$TARGET_DIR" -maxdepth 1 -type f -print0)
echo ""
echo "=== Summary ==="
echo "Total files found: $TOTAL"
echo ""
if $DRY_RUN; then
echo "Run without --dry-run to move files."
exit 0
fi
# Create dirs and move
for cat in "${!COUNTS[@]}"; do
mkdir -p "$TARGET_DIR/$cat"
done
while IFS= read -r -d '' file; do
rel="${file#$TARGET_DIR/}"
base="$(basename "$rel")"
ext="${base##*.}"
[ "$ext" = "$base" ] && continue
[[ "$base" == .* ]] && continue
ext_lc=$(echo "$ext" | tr '[:upper:]' '[:lower:]')
cat="${CAT_MAP[$ext_lc]:-Others}"
# handle name collision
dest="$TARGET_DIR/$cat/$base"
if [ -f "$dest" ]; then
name_no_ext="${base%.*}"
dest="$TARGET_DIR/$cat/${name_no_ext}_$(date +%Y%m%d_%H%M%S).$ext"
fi
mv "$file" "$dest"
done < <(find "$TARGET_DIR" -maxdepth 1 -type f -print0)
echo "=== Organization Report ==="
printf "%-20s %s\n" "Category" "Files"
printf "%-20s %s\n" "--------" "-----"
for cat in Documents Images Videos Music Archives Code Executables Fonts Others; do
[ -n "${COUNTS[$cat]}" ] && printf "%-20s %d\n" "$cat" "${COUNTS[$cat]}"
done
echo ""
echo "Done! Files organized in: $TARGET_DIR"
Always offer to do a dry-run before actually moving files. Run with --dry-run:
bash <<'SCRIPT'
TARGET_DIR="$HOME/Desktop"
# ... (same script with DRY_RUN=true)
SCRIPT
If the user wants to undo, the action is not reversible via script (files have been moved). You can restore by re-organizing within each category folder, but the simplest path is:
find "$TARGET_DIR" -mindepth 2 -type f -exec mv {} "$TARGET_DIR" \;
find, mkdir, mv共 2 个版本