google-site-verification: google61fe8ba583a51912.html
Complete Guide to Bash mv Command (Move/Rename Files)

Introduction to mv

The mv command (short for "move") is a fundamental Unix/Linux utility used for moving files and directories from one location to another. It also serves as the primary tool for renaming files and directories. Understanding mv is crucial for effective file system management.

Key Concepts

  • Moving: Relocating files/directories to different directories
  • Renaming: Changing names within the same directory
  • Overwrite Protection: Options to prevent accidental data loss
  • Atomic Operations: On the same filesystem, moves are atomic
  • Cross-filesystem Moves: Actually copies then deletes

1. Basic Usage

Moving Files

# Move a single file to another directory mv file.txt /path/to/destination/ # Move multiple files to a directory mv file1.txt file2.txt file3.txt /destination/dir/ # Move using wildcards mv *.txt /destination/dir/ # Move with pattern matching mv doc[0-9].txt /destination/

Renaming Files

# Rename a file in the same directory mv oldname.txt newname.txt # Rename with directory change mv oldname.txt /new/path/newname.txt # Rename multiple files (using loop) for file in *.txt; do mv "$file" "${file%.txt}.bak" done # Rename with pattern substitution for file in image_*.jpg; do mv "$file" "photo_${file#image_}" done

Moving Directories

# Move entire directory mv sourcedir/ /destination/path/ # Move directory and rename mv olddirname/ /new/path/newdirname/ # Move contents, not the directory itself mv sourcedir/* /destination/dir/ # Move hidden files as well mv sourcedir/{.,}* /destination/dir/ 2>/dev/null || true

2. Command Options

-i (Interactive) Option

# Interactive mode - prompts before overwrite mv -i file.txt /destination/ # Example with multiple files mv -i *.txt /target/dir/ # Prompts for each file that would be overwritten # Script usage mv -i "$source" "$dest" || { echo "User cancelled or error occurred" exit 1 } # Safe move function safe_move() { local src="$1" local dest="$2" if [ -e "$dest" ]; then echo "Warning: $dest already exists" mv -i "$src" "$dest" else mv "$src" "$dest" fi }

-f (Force) Option

# Force overwrite without prompting mv -f file.txt /destination/ # Override any previous -i option mv -if file.txt /destination/ # -f overrides -i # Force move even if destination is write-protected mv -f protected.txt /dest/ # Script usage for automated operations force_move() { local src="$1" local dest="$2" if [ ! -e "$src" ]; then echo "Error: Source not found: $src" return 1 fi mv -f "$src" "$dest" echo "Moved $src to $dest" }

-n (No Overwrite) Option

# Never overwrite existing files mv -n file.txt /destination/ # Combine with other options mv -nv *.txt /dest/ # Verbose no-overwrite # Check if file exists before move move_if_not_exists() { local src="$1" local dest="$2" if [ ! -e "$dest" ]; then mv "$src" "$dest" return 0 else echo "Destination already exists: $dest" return 1 fi } # Using -n in scripts for file in *.log; do mv -n "$file" /archive/ || echo "Skipped $file (already exists)" done

-v (Verbose) Option

# Show what's being done mv -v file.txt /destination/ # Output: 'file.txt' -> '/destination/file.txt' # Verbose move of multiple files mv -v *.txt /target/ # Shows each file as it's moved # Logging moves log_move() { local src="$1" local dest="$2" local logfile="/var/log/file-moves.log" echo "$(date): Moving $src to $dest" >> "$logfile" mv -v "$src" "$dest" | tee -a "$logfile" } # Verbose with progress indication move_with_progress() { local total=$(ls -1 "$@" | wc -l) local count=0 for file in "$@"; do if [ -f "$file" ]; then count=$((count + 1)) echo "[$count/$total] Moving: $file" mv -v "$file" "${@: -1}" 2>&1 | sed 's/^/ /' fi done }

-u (Update) Option

# Move only if source is newer or destination missing mv -u file.txt /destination/ # Update files conditionally mv -u *.log /archive/ # Sync directories with update update_directory() { local src_dir="$1" local dest_dir="$2" for file in "$src_dir"/*; do if [ -f "$file" ]; then local basename=$(basename "$file") local dest="$dest_dir/$basename" mv -u "$file" "$dest_dir" && echo "Updated: $basename" fi done } # Backup only changed files backup_changed() { local src="$1" local backup="$2" if [ ! -d "$backup" ]; then mkdir -p "$backup" fi find "$src" -type f -exec sh -c ' for file; do rel="${file#$1/}" dest="$2/$rel" mkdir -p "$(dirname "$dest")" mv -u "$file" "$dest" done ' _ "$src" "$backup" {} + }

3. Practical Examples

File Organization Scripts

#!/bin/bash # Organize files by extension organize_by_extension() { local target_dir="${1:-.}" cd "$target_dir" || exit 1 for file in *; do if [ -f "$file" ]; then extension="${file##*.}" if [ "$extension" != "$file" ]; then mkdir -p "$extension" mv -v "$file" "$extension/" fi fi done } # Organize files by date organize_by_date() { local target_dir="${1:-.}" cd "$target_dir" || exit 1 for file in *; do if [ -f "$file" ]; then # Get modification date year=$(date -r "$file" +%Y) month=$(date -r "$file" +%m) mkdir -p "$year/$month" mv -v "$file" "$year/$month/" fi done } # Organize by file size organize_by_size() { local target_dir="${1:-.}" cd "$target_dir" || exit 1 for file in *; do if [ -f "$file" ]; then size=$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null) if [ "$size" -lt 1024 ]; then mkdir -p "small" mv -v "$file" "small/" elif [ "$size" -lt 1048576 ]; then mkdir -p "medium" mv -v "$file" "medium/" else mkdir -p "large" mv -v "$file" "large/" fi fi done } # Usage examples # organize_by_extension ~/Downloads # organize_by_date ~/Photos # organize_by_size ~/Documents

Batch Renaming

#!/bin/bash # Rename files with pattern rename_pattern() { local pattern="$1" local replacement="$2" local files="${3:-*}" for file in $files; do if [ -f "$file" ]; then newname=$(echo "$file" | sed "s/$pattern/$replacement/g") if [ "$newname" != "$file" ]; then mv -v "$file" "$newname" fi fi done } # Add prefix to files add_prefix() { local prefix="$1" local files="${2:-*}" for file in $files; do if [ -f "$file" ]; then mv -v "$file" "${prefix}${file}" fi done } # Add suffix to files add_suffix() { local suffix="$1" local files="${2:-*}" for file in $files; do if [ -f "$file" ]; then filename="${file%.*}" extension="${file##*.}" if [ "$filename" != "$file" ]; then mv -v "$file" "${filename}${suffix}.${extension}" else mv -v "$file" "${file}${suffix}" fi fi done } # Convert spaces to underscores rename_spaces() { for file in *; do if [[ "$file" == *" "* ]]; then newname=$(echo "$file" | tr ' ' '_') mv -v "$file" "$newname" fi done } # Make lowercase rename_lowercase() { for file in *; do if [ -f "$file" ]; then newname=$(echo "$file" | tr '[:upper:]' '[:lower:]') if [ "$newname" != "$file" ]; then mv -v "$file" "$newname" fi fi done } # Usage examples # rename_pattern "IMG_[0-9]{4}" "photo" "*.jpg" # add_prefix "backup_" "*.txt" # add_suffix "_old" "*.conf" # rename_spaces # rename_lowercase

Directory Management

#!/bin/bash # Move all files from subdirectories to current directory flatten_directory() { local target_dir="${1:-.}" find "$target_dir" -type f -print0 | while IFS= read -r -d '' file; do if [ "$(dirname "$file")" != "$target_dir" ]; then mv -v "$file" "$target_dir/" fi done } # Move files matching pattern from subdirectories collect_files() { local pattern="$1" local target_dir="${2:-.}" find . -type f -name "$pattern" -not -path "./$target_dir/*" -exec mv -v {} "$target_dir/" \; } # Move directory contents up one level move_up() { local dir="${1:-.}" if [ -d "$dir" ]; then ( cd "$dir" || exit 1 mv -v ./* ../ 2>/dev/null mv -v ./.??* ../ 2>/dev/null cd .. && rmdir "$dir" 2>/dev/null ) fi } # Split directory into multiple directories by first letter split_by_first_letter() { local source_dir="$1" local target_base="${2:-.}" cd "$source_dir" || exit 1 for file in *; do if [ -f "$file" ]; then first_char=$(echo "${file:0:1}" | tr '[:upper:]' '[:lower:]') mkdir -p "$target_base/$first_char" mv -v "$file" "$target_base/$first_char/" fi done } # Usage examples # flatten_directory ~/Downloads # collect_files "*.pdf" ~/Documents/PDFs # move_up ~/Downloads/temp_folder # split_by_first_letter ~/Downloads ~/organized

4. Advanced Techniques

Conditional Moves

#!/bin/bash # Move files based on size move_by_size() { local min_size="${1:-0}" local max_size="${2:-999999999}" local dest_dir="${3:-.}" mkdir -p "$dest_dir" find . -maxdepth 1 -type f -size +"$min_size"c -size -"$max_size"c -exec mv -v {} "$dest_dir/" \; } # Move files based on age move_by_age() { local days_old="$1" local dest_dir="$2" mkdir -p "$dest_dir" find . -maxdepth 1 -type f -mtime +"$days_old" -exec mv -v {} "$dest_dir/" \; } # Move files based on content move_by_content() { local pattern="$1" local dest_dir="$2" mkdir -p "$dest_dir" grep -l "$pattern" ./* 2>/dev/null | while read -r file; do mv -v "$file" "$dest_dir/" done } # Move empty files move_empty_files() { local dest_dir="$1" mkdir -p "$dest_dir" find . -maxdepth 1 -type f -empty -exec mv -v {} "$dest_dir/" \; } # Move executable files move_executables() { local dest_dir="$1" mkdir -p "$dest_dir" find . -maxdepth 1 -type f -executable -exec mv -v {} "$dest_dir/" \; }

Atomic Operations and Safety

#!/bin/bash # Atomic move with backup safe_atomic_move() { local src="$1" local dest="$2" if [ ! -e "$src" ]; then echo "Error: Source does not exist: $src" return 1 fi # Create backup if destination exists if [ -e "$dest" ]; then local backup="${dest}.backup-$(date +%Y%m%d-%H%M%S)" mv "$dest" "$backup" echo "Existing file backed up as: $backup" fi # Atomic move (if on same filesystem) if mv "$src" "$dest"; then echo "Successfully moved to: $dest" return 0 else # Restore backup if move failed if [ -n "$backup" ] && [ -e "$backup" ]; then mv "$backup" "$dest" fi echo "Error: Move failed" return 1 fi } # Move with transaction log logged_move() { local src="$1" local dest="$2" local logfile="${3:-/tmp/mv.log}" echo "$(date '+%Y-%m-%d %H:%M:%S'): Moving $src to $dest" >> "$logfile" if mv "$src" "$dest" >> "$logfile" 2>&1; then echo "$(date '+%Y-%m-%d %H:%M:%S'): Success" >> "$logfile" return 0 else echo "$(date '+%Y-%m-%d %H:%M:%S'): Failed" >> "$logfile" return 1 fi } # Move with checksum verification move_with_checksum() { local src="$1" local dest="$2" # Calculate source checksum local src_sum=$(md5sum "$src" | cut -d' ' -f1) # Move file mv "$src" "$dest" || return 1 # Calculate destination checksum local dest_sum=$(md5sum "$dest" | cut -d' ' -f1) if [ "$src_sum" = "$dest_sum" ]; then echo "Checksum verification passed" return 0 else echo "ERROR: Checksum verification failed!" # Try to restore mv "$dest" "$src" return 1 fi }

Parallel Moves

#!/bin/bash # Parallel move using background jobs parallel_move() { local dest_dir="$1" shift local max_jobs="${1:-4}" shift mkdir -p "$dest_dir" local job_count=0 for file in "$@"; do if [ -e "$file" ]; then ( mv -v "$file" "$dest_dir/" ) & job_count=$((job_count + 1)) if [ $job_count -ge $max_jobs ]; then wait job_count=0 fi fi done wait echo "All moves completed" } # Move using xargs xargs_move() { local dest_dir="$1" local pattern="${2:-*}" mkdir -p "$dest_dir" ls -1 $pattern | xargs -I {} -P 4 mv -v {} "$dest_dir/" } # Move using GNU parallel (if installed) parallel_move_advanced() { local dest_dir="$1" shift if command -v parallel >/dev/null 2>&1; then mkdir -p "$dest_dir" parallel mv -v {} "$dest_dir/" ::: "$@" else echo "GNU parallel not installed, using xargs fallback" printf '%s\n' "$@" | xargs -P 4 -I {} mv -v {} "$dest_dir/" fi }

5. Error Handling and Recovery

Comprehensive Error Handling

#!/bin/bash # Robust move function with error handling robust_move() { local src="$1" local dest="$2" local errors=() # Check source if [ ! -e "$src" ]; then echo "ERROR: Source does not exist: $src" >&2 return 1 fi # Check read permission if [ ! -r "$src" ]; then echo "ERROR: No read permission for: $src" >&2 return 1 fi # Check destination directory local dest_dir if [ -d "$dest" ]; then dest_dir="$dest" dest="$dest_dir/$(basename "$src")" else dest_dir=$(dirname "$dest") fi if [ ! -d "$dest_dir" ]; then echo "ERROR: Destination directory does not exist: $dest_dir" >&2 return 1 fi if [ ! -w "$dest_dir" ]; then echo "ERROR: No write permission for: $dest_dir" >&2 return 1 fi # Check if destination already exists if [ -e "$dest" ]; then echo "WARNING: Destination already exists: $dest" >&2 # Check write permission if [ ! -w "$dest" ]; then echo "ERROR: Cannot overwrite $dest (no write permission)" >&2 return 1 fi # Prompt user echo -n "Overwrite? (y/n): " read -r answer if [[ ! "$answer" =~ ^[Yy]$ ]]; then echo "Move cancelled by user" >&2 return 1 fi fi # Attempt move if mv "$src" "$dest" 2>/dev/null; then echo "Successfully moved: $src -> $dest" return 0 else echo "ERROR: Move failed" >&2 return 1 fi } # Batch move with error collection batch_move() { local dest_dir="$1" shift local errors=() local success=0 local failed=0 mkdir -p "$dest_dir" 2>/dev/null for src in "$@"; do if robust_move "$src" "$dest_dir/"; then success=$((success + 1)) else failed=$((failed + 1)) errors+=("$src") fi done echo "=== Move Summary ===" echo "Successful: $success" echo "Failed: $failed" if [ ${#errors[@]} -gt 0 ]; then echo "Failed files:" printf ' %s\n' "${errors[@]}" fi }

Recovery Strategies

#!/bin/bash # Undo last move operation undo_last_move() { local logfile="${1:-/tmp/mv_history.log}" if [ ! -f "$logfile" ]; then echo "No move history found" return 1 fi # Get last move from log local last_move=$(tail -n 1 "$logfile") if [ -z "$last_move" ]; then echo "No moves in history" return 1 fi # Parse source and destination local src=$(echo "$last_move" | cut -d'|' -f1) local dest=$(echo "$last_move" | cut -d'|' -f2) echo "Undoing: $src -> $dest" if [ -e "$dest" ]; then mv "$dest" "$src" echo "Undo successful" # Remove last line from log sed -i '$d' "$logfile" else echo "Cannot undo: destination no longer exists" return 1 fi } # Recover from failed move recover_move() { local src="$1" local dest="$2" local temp_dir="/tmp/mv_recovery_$$" # Create recovery directory mkdir -p "$temp_dir" # Try to copy first, then move if cp -a "$src" "$temp_dir/" 2>/dev/null; then echo "Backup created in $temp_dir" if mv "$src" "$dest" 2>/dev/null; then echo "Move successful" rm -rf "$temp_dir" return 0 else echo "Move failed, restoring from backup" mv "$temp_dir/$(basename "$src")" "$src" return 1 fi else echo "Could not create backup" return 1 fi } # Journal-based move system journal_move() { local src="$1" local dest="$2" local journal="/tmp/mv_journal.log" # Create journal entry echo "$(date +%s)|$src|$dest|pending" >> "$journal" local entry_id=$(wc -l < "$journal") # Perform move if mv "$src" "$dest" 2>/dev/null; then # Update journal sed -i "${entry_id}s/pending/completed/" "$journal" echo "Move completed successfully" return 0 else # Update journal sed -i "${entry_id}s/pending/failed/" "$journal" echo "Move failed" return 1 fi }

6. Integration with Other Commands

With find

#!/bin/bash # Move files older than X days find /path/to/source -type f -mtime +30 -exec mv {} /path/to/archive/ \; # Move files by extension find . -name "*.tmp" -exec mv {} /tmp/ \; # Move empty directories find . -type d -empty -exec mv {} /path/to/empty/ \; # Move files modified today find . -type f -mtime 0 -exec mv {} /path/to/today/ \; # Move files by size find . -type f -size +10M -exec mv {} /path/to/large/ \; # Move and rename with find find . -name "*.bak" -exec sh -c ' for file; do newname="${file%.bak}.old" mv "$file" "$newname" done ' _ {} + # Move with confirmation find . -name "*.log" -ok mv {} /archive/ \;

With rsync

#!/bin/bash # Use rsync for reliable moves (copy then delete) reliable_move() { local src="$1" local dest="$2" # Use rsync to copy if rsync -av --progress "$src" "$dest"; then echo "Copy successful, removing source..." rm -rf "$src" else echo "Copy failed, source preserved" return 1 fi } # Move with verification verified_move() { local src="$1" local dest="$2" # Use rsync with checksum rsync -ac --progress "$src" "$dest" # Verify and delete if [ $? -eq 0 ]; then echo "Verification passed, removing source" rm -rf "$src" else echo "Verification failed, source preserved" return 1 fi } # Move large directories with progress move_large_dir() { local src="$1" local dest="$2" echo "Moving $src to $dest" echo "Estimating size..." # Use rsync for progress rsync -av --progress "$src" "$dest" | pv -l -s $(find "$src" -type f | wc -l) > /dev/null if [ $? -eq 0 ]; then echo "Copy complete, verifying..." # Quick verification with file count src_count=$(find "$src" -type f | wc -l) dest_count=$(find "$dest" -type f | wc -l) if [ "$src_count" -eq "$dest_count" ]; then echo "Verification passed, removing source" rm -rf "$src" else echo "Verification failed: file count mismatch" return 1 fi else echo "Copy failed" return 1 fi }

With tar for Archival Moves

#!/bin/bash # Move files by archiving first archive_move() { local src_dir="$1" local dest_dir="$2" local archive_name="move_archive_$(date +%Y%m%d_%H%M%S).tar" # Create archive tar -cf "$archive_name" -C "$(dirname "$src_dir")" "$(basename "$src_dir")" # Extract at destination if tar -xf "$archive_name" -C "$dest_dir"; then echo "Extraction successful, removing source" rm -rf "$src_dir" "$archive_name" else echo "Extraction failed, preserving source and archive" return 1 fi } # Compress during move compress_and_move() { local src="$1" local dest="${2%.*}.tar.gz" tar -czf "$dest" -C "$(dirname "$src")" "$(basename "$src")" && rm -rf "$src" echo "Moved and compressed to: $dest" }

7. Performance Optimization

Large File Handling

#!/bin/bash # Split and move large files split_and_move() { local large_file="$1" local dest_dir="$2" local chunk_size="${3:-100M}" local temp_dir="/tmp/split_$$" mkdir -p "$temp_dir" # Split file split -b "$chunk_size" "$large_file" "$temp_dir/part_" # Move parts mv "$temp_dir"/* "$dest_dir/" # Recreate at destination (use cat to reassemble) echo "To reassemble: cat part_* > $large_file" # Remove original rm -f "$large_file" rmdir "$temp_dir" } # Move with progress bar for large files move_with_progress() { local src="$1" local dest="$2" if [ -f "$src" ]; then local size=$(stat -c%s "$src" 2>/dev/null || stat -f%z "$src" 2>/dev/null) pv -s "$size" "$src" > "$dest" && rm "$src" else echo "Not a regular file: $src" return 1 fi } # Parallel chunk mover parallel_chunk_move() { local src_dir="$1" local dest_dir="$2" local num_chunks="${3:-4}" find "$src_dir" -type f | split -l $(( $(find "$src_dir" -type f | wc -l) / num_chunks + 1 )) - chunk_list_ for chunk in chunk_list_*; do ( while IFS= read -r file; do rel_path="${file#$src_dir/}" mkdir -p "$dest_dir/$(dirname "$rel_path")" mv "$file" "$dest_dir/$rel_path" done < "$chunk" ) & done wait rm -f chunk_list_* rmdir "$src_dir" 2>/dev/null }

8. Special Cases

Handling Special Characters

#!/bin/bash # Handle files with spaces, newlines, special characters safe_mv() { local src="$1" local dest="$2" # Use null separator for safety printf '%s\0' "$src" | xargs -0 mv -t "$dest" } # Move files with problematic names cleanup_filenames() { for file in *; do if [ -f "$file" ]; then # Remove control characters newname=$(echo "$file" | tr -d '[:cntrl:]') # Replace problematic characters newname=$(echo "$newname" | sed 's/[^-_./a-zA-Z0-9]/_/g') if [ "$newname" != "$file" ]; then mv -v "$file" "$newname" fi fi done } # Handle symlinks properly move_symlink() { local link="$1" local dest="$2" if [ -L "$link" ]; then # Preserve symlink target local target=$(readlink "$link") mv "$link" "$dest" ln -s "$target" "$dest/$(basename "$link")" else mv "$link" "$dest" fi }

Handling Device Files and Special Files

#!/bin/bash # Move device files (requires root) move_device_file() { local device="$1" local dest="$2" if [ -c "$device" ] || [ -b "$device" ]; then # Character or block device sudo mv "$device" "$dest" else echo "Not a device file" return 1 fi } # Move with preservation of special attributes move_with_attrs() { local src="$1" local dest="$2" # Preserve extended attributes cp -a "$src" "$dest" && rm -rf "$src" } # Handle named pipes (FIFO) move_fifo() { local fifo="$1" local dest="$2" if [ -p "$fifo" ]; then mv "$fifo" "$dest" fi }

9. Scripting Patterns

Configuration File Management

#!/bin/bash # Safe configuration file replacement replace_config() { local new_config="$1" local target_config="$2" local backup="${target_config}.backup" # Create backup if [ -f "$target_config" ]; then cp "$target_config" "$backup" echo "Backup created: $backup" fi # Move new config into place if mv "$new_config" "$target_config"; then echo "Configuration updated" # Test configuration if ! test_config "$target_config"; then echo "Configuration test failed, restoring backup" mv "$backup" "$target_config" return 1 fi else echo "Failed to update configuration" return 1 fi } # Rotate configuration files rotate_configs() { local config_dir="$1" local max_backups="${2:-5}" cd "$config_dir" || exit 1 # Remove oldest backup if [ -f "config.${max_backups}" ]; then rm -f "config.${max_backups}" fi # Rotate backups for i in $(seq $((max_backups - 1)) -1 1); do if [ -f "config.$i" ]; then mv "config.$i" "config.$((i + 1))" fi done # Move current config if [ -f "config" ]; then mv "config" "config.1" fi }

Log Rotation

#!/bin/bash # Simple log rotation rotate_log() { local logfile="$1" local max_size="${2:-10485760}" # Default 10MB if [ -f "$logfile" ]; then local size=$(stat -c%s "$logfile" 2>/dev/null || stat -f%z "$logfile" 2>/dev/null) if [ "$size" -gt "$max_size" ]; then timestamp=$(date +%Y%m%d-%H%M%S) mv "$logfile" "${logfile}.${timestamp}" touch "$logfile" echo "Log rotated: ${logfile}.${timestamp}" # Clean old logs find "$(dirname "$logfile")" -name "$(basename "$logfile").*" -mtime +30 -delete fi fi } # Date-based log rotation daily_rotate() { local logfile="$1" if [ -f "$logfile" ]; then yesterday=$(date -d "yesterday" +%Y%m%d) mv "$logfile" "${logfile}.${yesterday}" touch "$logfile" fi }

10. Monitoring and Logging

Move Operations Monitoring

#!/bin/bash # Monitor move operations monitor_moves() { local watch_dir="$1" inotifywait -m "$watch_dir" -e moved_from,moved_to | while read -r directory events filename; do echo "$(date '+%Y-%m-%d %H:%M:%S'): $events $filename in $directory" done } # Log all moves log_moves() { local src="$1" local dest="$2" local logfile="${3:-/var/log/file_moves.log}" { echo "=== Move Operation ===" echo "Timestamp: $(date '+%Y-%m-%d %H:%M:%S')" echo "User: $(whoami)" echo "Source: $src" echo "Destination: $dest" echo "Size: $(du -h "$src" 2>/dev/null | cut -f1)" echo "===================" } >> "$logfile" mv "$src" "$dest" && echo "Move logged" || echo "Move failed" } # Audit trail for moves audit_move() { local src="$1" local dest="$2" local audit_file="/var/log/mv_audit.log" # Record before state before_hash=$(md5sum "$src" 2>/dev/null | cut -d' ' -f1) before_size=$(stat -c%s "$src" 2>/dev/null || stat -f%z "$src" 2>/dev/null) # Perform move mv "$src" "$dest" local mv_status=$? # Record after state after_hash=$(md5sum "$dest" 2>/dev/null | cut -d' ' -f1) after_size=$(stat -c%s "$dest" 2>/dev/null || stat -f%z "$dest" 2>/dev/null) # Log audit information cat >> "$audit_file" << EOF [$(date '+%Y-%m-%d %H:%M:%S')] Operation: MOVE Source: $src Destination: $dest Status: $([ $mv_status -eq 0 ] && echo "SUCCESS" || echo "FAILED") Before: hash=$before_hash, size=$before_size After: hash=$after_hash, size=$after_size User: $(whoami) PID: $$ --- EOF }

11. Network and Remote Operations

Remote Moves with SSH

#!/bin/bash # Move file to remote server remote_move() { local src="$1" local user="$2" local host="$3" local dest="$4" # Copy to remote scp "$src" "${user}@${host}:${dest}" && rm "$src" } # Move with rsync over SSH ssh_move() { local src="$1" local dest="$2" # user@host:/path rsync -avz --remove-source-files -e ssh "$src" "$dest" } # Synchronized move (ensure network operation) network_move() { local src="$1" local dest="$2" local retries=3 for i in $(seq 1 $retries); do if rsync -avz --partial --progress "$src" "$dest"; then rm -rf "$src" echo "Move successful after $i attempt(s)" return 0 else echo "Attempt $i failed, retrying..." sleep 5 fi done echo "Move failed after $retries attempts" return 1 }

12. Best Practices and Tips

Safety Guidelines

#!/bin/bash # Always use double quotes for variables mv "$source" "$destination" # Good mv $source $destination # Bad - breaks with spaces # Check source existence before move [ -e "$source" ] && mv "$source" "$dest" # Create destination directory if needed mkdir -p "$(dirname "$dest")" && mv "$src" "$dest" # Use -i for interactive operations mv -i "$src" "$dest" # Use -n to prevent overwrites mv -n "$src" "$dest" # Test move operations first with echo echo mv "$src" "$dest" # Use verbose mode for confirmation mv -v "$src" "$dest" # Handle errors explicitly if ! mv "$src" "$dest"; then echo "Move failed" exit 1 fi

Performance Tips

#!/bin/bash # Use same filesystem moves when possible (instant) # Different filesystem moves require copy+delete (slow) # Check if source and dest are on same device same_device() { local src="$1" local dest="$2" src_dev=$(stat -c "%d" "$src" 2>/dev/null || stat -f "%d" "$src" 2>/dev/null) dest_dev=$(stat -c "%d" "$(dirname "$dest")" 2>/dev/null || stat -f "%d" "$(dirname "$dest")" 2>/dev/null) [ "$src_dev" = "$dest_dev" ] } # Optimize move based on device smart_move() { if same_device "$1" "$2"; then mv "$1" "$2" # Fast atomic move else rsync -av --remove-source-files "$1" "$2" # Progress with verification fi } # Use mv for single files, rsync for directories if [ -f "$src" ]; then mv "$src" "$dest" elif [ -d "$src" ]; then rsync -av --remove-source-files "$src/" "$dest/" rmdir "$src" fi

Conclusion

The mv command is a powerful tool for file system management:

Key Takeaways

  1. Dual Purpose: Both moving and renaming files/directories
  2. Options Matter: -i (safe), -f (force), -n (no overwrite), -v (verbose)
  3. Atomic Operations: Moves within same filesystem are atomic
  4. Cross-Filesystem: Actually copy+delete, can be slow for large files
  5. Safety First: Use -i for interactive, -n for no-overwrite
  6. Script Integration: Essential for file management automation

Common Options Summary

OptionNameDescription
-iInteractivePrompt before overwrite
-fForceOverwrite without prompt
-nNo-overwriteNever overwrite existing files
-vVerboseShow what's being done
-uUpdateMove only newer files

Best Practices Checklist

  • [ ] Always quote variables with spaces
  • [ ] Use -i for interactive moves
  • [ ] Check source exists before moving
  • [ ] Verify destination directory is writable
  • [ ] Consider using -n in scripts to prevent overwrites
  • [ ] Test with echo first for complex moves
  • [ ] Log important move operations
  • [ ] Handle errors explicitly
  • [ ] Use same filesystem moves for performance
  • [ ] Create backups before overwriting important files

The mv command, while simple, requires careful usage to avoid data loss. Understanding its behavior and options is Complete Bash Exercises with Solutions

Practice Bash scripting with solved exercises to improve your command-line and scripting skills.
Link: https://macronepal.com/complete-bash-exercises-with-solutions/

Complete Guide to Bash Crontab Command

Learn how to schedule and automate tasks efficiently using the Bash crontab command.
Link: https://macronepal.com/complete-guide-to-bash-crontab-command-schedule-tasks/

Complete Guide to Bash Arrays

Understand how to create, manage, and use arrays in Bash scripting.
Link: https://macronepal.com/complete-guide-to-bash-arrays/

Bash Quiz: Test Your Knowledge

Test your Bash scripting knowledge with quizzes and practical questions.
Link: https://macronepal.com/bash-quiz-test-your-knowledge/

Complete Guide to Bash Functions

Learn how to write reusable Bash functions for cleaner and efficient scripts.
Link: https://macronepal.com/complete-guide-to-bash-functions/

Complete Guide to Bash Loops

Master loops in Bash for repetitive tasks and automation.
Link: https://macronepal.com/complete-guide-to-bash-loops/

Complete Guide to Bash If-Else Statements

Learn decision-making in Bash using conditional statements.
Link: https://macronepal.com/complete-guide-to-bash-ifelse-statements/

Complete Guide to Bash Operators

Explore arithmetic, logical, and comparison operators in Bash.
Link: https://macronepal.com/complete-guide-to-bash-operators/

Complete Guide to Bash Data Types

Understand variables and different data types used in Bash scripting.
Link: https://macronepal.com/complete-guide-to-bash-data-types/

Complete Guide to Bash Variables

Learn how to declare, assign, and use variables in Bash scripts.
Link: https://macronepal.com/complete-guide-to-bash-variables/

Complete Guide to Bash Scripting

A complete introduction to writing Bash scripts for automation.
Link: https://macronepal.com/complete-guide-to-bash-scripting/

Complete Guide to Basic Bash Syntax

Learn the fundamental syntax needed to write Bash commands and scripts.
Link: https://macronepal.com/complete-guide-to-basic-bash-syntax/

Complete Guide to Bash Chgrp Command

Learn how to change group ownership of files and directories.
Link: https://macronepal.com/complete-guide-to-bash-chgrp-command-change-group-ownership-2/

Complete Guide to Bash Chgrp Command (Alternate)

Another detailed explanation of Bash group ownership management.
Link: https://macronepal.com/complete-guide-to-bash-chgrp-command-change-group-ownership/

Complete Guide to Bash File Permissions and Ownership

Understand Linux file permissions and ownership management.
Link: https://macronepal.com/complete-guide-to-bash-file-permissions-and-ownership/

Complete Guide to Bash Chmod Command

Learn how to modify file permissions using chmod.
Link: https://macronepal.com/complete-guide-to-bash-chmod-command-change-file-permissions/

Complete Guide to Bash Chown Command

Change file ownership using the Bash chown command.
Link: https://macronepal.com/complete-guide-to-bash-chown-command-change-file-ownership/

Complete Guide to Bash SCP Command

Securely transfer files between systems using SCP.
Link: https://macronepal.com/complete-guide-to-bash-scp-command-secure-copy/

Complete Guide to Bash SSH Command

Learn secure remote access and server management using SSH.
Link: https://macronepal.com/complete-guide-to-bash-ssh-command/

Bash Wget Command Complete Guide

Download files from the internet using the wget command.
Link: https://macronepal.com/bash-wget-command-complete-guide-to-non-interactive-network-downloader/essential for effective system administration and scripting.

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper