#!/bin/bash # swap - swap two files by renaming via a temp file # # Usage: # swap # # Options: # -h, --help Show help message _swap() ( local SCRIPT_NAME; SCRIPT_NAME="$(basename "${BASH_SOURCE[0]}")" case "${BASH_SOURCE[0]}" in /dev/*|/proc/*) SCRIPT_NAME="" ;; esac case "$SCRIPT_NAME" in ""|bash|sh|zsh|dash) SCRIPT_NAME="swap" ;; esac _show_help() { local s; [ -t 1 ] && s=$'\033[4m' local r; [ -t 1 ] && r=$'\033[24m' cat < first) 10 Failed to move temp to second (no restore attempted: second already moved) EOF } _error() { echo "[ERR][$SCRIPT_NAME] $*" >&2; } case "$1" in -h|--help) _show_help return 0 ;; esac if [ $# -lt 2 ]; then _error "Must provide two files to swap (received $#). Run \`$SCRIPT_NAME -h\` for usage" return 2 fi local file1="$1" local file2="$2" # Validate first file if [ ! -e "$file1" ]; then _error "File '$file1' does not exist" return 4 elif [ -d "$file1" ]; then _error "'$file1' is a directory" return 5 fi # Validate second file if [ ! -e "$file2" ]; then _error "File '$file2' does not exist" return 6 elif [ -d "$file2" ]; then _error "'$file2' is a directory" return 7 fi # Create a unique temporary filename for swapping local basename; basename="$(basename "$file1")" local temp_file="/tmp/temp-swap-$basename" while [ -e "$temp_file" ]; do temp_file="/tmp/temp-swap-$basename-$$-$RANDOM" done # Perform the swap using `mv`. Return distinct codes for each failure point if ! mv "$file1" "$temp_file"; then # file1 -> temp _error "Failed to move '$file1' to temporary file '$temp_file'" return 8 fi if ! mv "$file2" "$file1"; then # file2 -> file1 _error "Failed to move '$file2' to '$file1'" # Move failed - Attempt to restore the original file if ! mv "$temp_file" "$file1"; then _error "Failed to restore '$temp_file' to '$file1'" fi return 9 fi if ! mv "$temp_file" "$file2"; then # temp -> file2 _error "Failed to move temporary file to '$file2'" return 10 fi # 0 status code is implied, but we will be explicit return 0 ) _swap "$@" __swap_rc=$? unset -f _swap if [ -n "${BASH_SOURCE[0]}" ] && [ "${BASH_SOURCE[0]}" != "$0" ]; then eval "unset __swap_rc; return $__swap_rc" fi eval "unset __swap_rc; exit $__swap_rc"