ext4文件系统下复制文件至目录时如何保留目标目录修改时间戳?
Great question—this is a super common pain point when doing bulk file copies on ext4. The issue is that any time you add, remove, or modify files inside a directory, ext4 automatically updates that directory's modification timestamp (mtime)—and tools like cp -a or rsync -a don't have a built-in way to avoid this.
The workaround is straightforward: save the target directory's timestamps before copying, then restore them once the copy is done. Here's how to implement this reliably, both for single directories and bulk scripted operations:
1. Single Directory Workflow
For a one-off copy, you can run these commands directly in your terminal:
# Define your target directory TARGET_DIR="/path/to/your/target/dir" # Save the target's current modification and access timestamps # We format them to a string `touch` can easily parse MTIME=$(stat -c "%Y%m%d%H%M.%S" "$TARGET_DIR") ATIME=$(stat -c "%X%m%d%H%M.%S" "$TARGET_DIR") # Run your copy operation (choose the tool that fits your needs) # Example 1: Copy files with rsync, preserving all file attributes rsync -a /path/to/source/files/* "$TARGET_DIR/" # Example 2: Copy with cp, preserving permissions, timestamps, etc. # cp -a /path/to/source/files/* "$TARGET_DIR/" # Restore the target directory's original timestamps touch -m -t "$MTIME" "$TARGET_DIR" # Restore modification time touch -a -t "$ATIME" "$TARGET_DIR" # Restore access time (optional but thorough)
2. Bulk Processing Script
If you need to handle dozens of source-target directory pairs, wrap the logic in a bash script for automation:
#!/bin/bash # Define your source-target directory pairs (add as many as needed) # Format: ["/path/to/source"]="/path/to/target" declare -A COPY_PAIRS=( ["/home/user/docs"]="/backup/server/docs" ["/home/user/photos"]="/backup/server/photos" ["/home/user/projects"]="/backup/server/projects" ) # Optional: Add trap to restore timestamps if script is interrupted trap ' if [ -n "$TARGET" ] && [ -n "$MTIME" ] && [ -n "$ATIME" ]; then echo "Script interrupted! Restoring timestamps for $TARGET" touch -m -t "$MTIME" "$TARGET" touch -a -t "$ATIME" "$TARGET" fi exit 1 ' INT TERM # Loop through each copy pair for SOURCE in "${!COPY_PAIRS[@]}"; do TARGET="${COPY_PAIRS[$SOURCE]}" # Skip if source or target doesn't exist if [ ! -d "$SOURCE" ]; then echo "Warning: Source directory $SOURCE not found - skipping" continue fi if [ ! -d "$TARGET" ]; then echo "Warning: Target directory $TARGET not found - skipping" continue fi # Save target timestamps MTIME=$(stat -c "%Y%m%d%H%M.%S" "$TARGET") ATIME=$(stat -c "%X%m%d%H%M.%S" "$TARGET") # Run bulk copy (--delete removes files in target that aren't in source; remove if not needed) rsync -a --delete "$SOURCE/" "$TARGET/" # Restore timestamps touch -m -t "$MTIME" "$TARGET" touch -a -t "$ATIME" "$TARGET" echo "Successfully processed: $SOURCE -> $TARGET (timestamps restored)" done
Key Notes
- Permissions: Make sure the user running the script has write access to the target directory—otherwise
touchwon't be able to restore the timestamps. - CTime Caveat: You can't manually modify a directory's change timestamp (ctime) on ext4 (it tracks when the directory's metadata was last altered, including timestamp changes). But since you're only concerned with preserving the modification time (mtime), this isn't an issue.
- Tool Flexibility: You can swap
rsyncforcpor another copy tool—just ensure it preserves the file attributes you need (like permissions, file timestamps).
内容的提问来源于stack exchange,提问作者Robert Murphy

