原因:
备份多文件夹,文件时打命令行容易出错,这个脚本诞生了。
使用方法:
1. 使用步骤:
将脚本intar.sh 链接到了 /usr/bin/intar
,可以在终端的任何位置直接运行它。
-
运行脚本 : 在终端中直接输入
intar
并按回车键。intar
-
添加备份路径 : 脚本会提示输入需要备份的文件或文件夹的完整路径。每次输入一个路径后按回车。
-
例如,输入
/var/log/nginx
来备份 Nginx 的日志目录。 -
例如,输入
/root/.bashrc
来备份您的 bash 配置文件。
-
-
完成添加 : 当添加完所有需要备份的项目后,在一个新的提示行直接按回车键(不输入任何内容),脚本就会知道已完成添加。
-
自动备份 : 脚本会自动开始备份过程。它会创建一个以当前日期和时间命名的、唯一的
.tar.gz
压缩文件,并保存在固定目录中。 -
查看结果: 备份完成后,脚本会显示成功信息以及最终备份文件的大小。
2. 备份文件位置
所有通过 intar
脚本创建的备份文件都会被统一保存在 /root/backups/
目录下。
3. 使用示例
假设您想备份 Nginx 的配置文件 (/etc/nginx
) 和您自己的脚本目录 (/root/scripts
)。
# 1. 运行命令
root@usw:~# intar
# 2. 脚本提示您输入路径
>> Please enter the full path for each file or folder you want to back up.
>> Press [ENTER] on an empty line when you are finished.
------------------------------------------------------------------
# 3. 输入第一个路径
Add path to backup (or press Enter to finish): /etc/nginx
+ Added: '/etc/nginx'
# 4. 输入第二个路径
Add path to backup (or press Enter to finish): /root/scripts
+ Added: '/root/scripts'
# 5. 在空行直接按回车,表示添加完毕
Add path to backup (or press Enter to finish):
------------------------------------------------------------------
>> Finished adding sources. Preparing the backup...
# 6. 脚本开始执行备份
>> Starting backup of 2 items...
Destination: /root/backups/backup-2025-09-25_10-50-12.tar.gz
a /etc/nginx/
a /etc/nginx/nginx.conf
... (此处会显示所有被添加的文件) ...
a /root/scripts/
a /root/scripts/intar.sh
# 7. 备份完成,显示结果
✅ Backup created successfully!
Archive size: 1.2M
现在,可以前往 /root/backups
目录找到名为 backup-2025-09-25_10-50-12.tar.gz
的备份文件。
(以上内容用 GEMINI 生成)
4. script code 文章最后有最新更新
file name: /root/scripts/intar.sh
cat << 'EOF' > /root/scripts/intar.sh
#!/bin/bash
# Write by Dave on 25Sep.25
# An interactive Bash script to use the tar to back up multiple files and folders.
## ==> START OF CONFIGURATION <== ##
# Set the destination directory for your backups.
# This is the only variable you need to configure in the script.
DESTINATION_DIR="/root/backups"
if [ -z "$DESTINATION_DIR" ]; then
echo "Error: DESTINATION_DIR is not set. Please configure it in the script." >&2
mkdir -p "$DESTINATION_DIR"
echo "Created backup directory at $DESTINATION_DIR"
exit 1
fi
## ==> END OF CONFIGURATION <== ##
# --- SCRIPT LOGIC ---
# 1. Ask for the items to back up.
echo ">> Please enter the full path for each file or folder you want to back up."
echo ">> Press [ENTER] on an empty line when you are finished."
echo "------------------------------------------------------------------"
# Initialize an empty array to store the sources.
SOURCES_TO_BACKUP=()
# Loop to read user input.
while true; do
read -p "Add path to backup (or press Enter to finish): " user_input
# If the user input is empty, break the loop.
if [ -z "$user_input" ]; then
break
fi
# Check if the file or folder actually exists.
if [ ! -e "$user_input" ]; then
echo " ⚠️ Warning: '$user_input' does not exist. It will be skipped."
continue
fi
# Add the valid path to our array.
SOURCES_TO_BACKUP+=("$user_input")
echo " + Added: '$user_input'"
done
# 2. Check if the user added any sources.
if [ ${#SOURCES_TO_BACKUP[@]} -eq 0 ]; then
echo "❌ No files or folders were added. Aborting backup." >&2
exit 1
fi
echo "------------------------------------------------------------------"
echo ">> Finished adding sources. Preparing the backup..."
# 3. Get the current date and time to create a unique filename.
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
BACKUP_FILENAME="backup-${TIMESTAMP}.tar.gz"
BACKUP_FILE="${DESTINATION_DIR}/${BACKUP_FILENAME}"
# 4. Check if the destination directory exists. If not, create it.
if [ ! -d "$DESTINATION_DIR" ]; then
echo ">> Destination directory not found. Creating it: ${DESTINATION_DIR}"
mkdir -p "$DESTINATION_DIR"
if [ $? -ne 0 ]; then
echo " Error: Could not create destination directory. Aborting." >&2
exit 1
fi
fi
# 5. Create the compressed tar archive.
echo ">> Starting backup of ${#SOURCES_TO_BACKUP[@]} items..."
echo " Destination: ${BACKUP_FILE}"
tar -czvf "$BACKUP_FILE" "${SOURCES_TO_BACKUP[@]}"
# 6. Verify that the backup was created successfully.
if [ $? -eq 0 ]; then
echo "✅ Backup created successfully!"
echo " Archive size: $(du -h "$BACKUP_FILE" | awk '{print $1}')"
else
echo "❌ Error: Backup failed. Please check the output above for errors." >&2
exit 1
fi
exit 0
EOF
chmod +x /root/scripts/intar.sh
ln -sf /root/scripts/intar.sh /usr/bin/intar
最后:
增加个任务记录与导入可能更方便。
添加了任务保存与导入功能
1. 演示


2. bash script:
#!/bin/bash
# Write by Dave on 25Sep.25 version 0.1
# Description: An interactive Bash script to use the tar to back up multiple files and folders.
# Updated: added task manager to save/load backup configurations version 0.2
clear
## ==> START OF CONFIGURATION <== ##
# Set the destination directory for your backups.
# This is the only variable you need to configure in the script.
DESTINATION_DIR="/root/backups"
# Directory to store saved tasks
TASKS_DIR="/root/backups/tasks"
if [ -z "$DESTINATION_DIR" ]; then
echo "Error: DESTINATION_DIR is not set. Please configure it in the script." >&2
mkdir -p "$DESTINATION_DIR"
echo "Created backup directory at $DESTINATION_DIR"
exit 1
fi
# Create tasks directory if it doesn't exist
mkdir -p "$TASKS_DIR"
## ==> END OF CONFIGURATION <== ##
# --- HELPER FUNCTIONS ---
# Function to list saved tasks and return array of task names
list_saved_tasks() {
echo ">> Available saved tasks:"
TASK_NAMES=() # Global array to store task names
if [ -d "$TASKS_DIR" ] && [ "$(ls -A "$TASKS_DIR"/*.task 2>/dev/null)" ]; then
local count=1
for task_file in "$TASKS_DIR"/*.task; do
if [ -f "$task_file" ]; then
local task_name=$(basename "$task_file" .task)
local task_count=$(wc -l < "$task_file" 2>/dev/null || echo "0")
echo " [$count] $task_name ($task_count items)"
TASK_NAMES+=("$task_name")
((count++))
fi
done
return 0
else
echo " No saved tasks found."
return 1
fi
}
# Function to get task name by number or name
get_task_name() {
local input="$1"
# If input is empty, return empty
if [ -z "$input" ]; then
echo ""
return
fi
# Check if input is a number
if [[ "$input" =~ ^[0-9]+$ ]]; then
local index=$((input - 1))
if [ $index -ge 0 ] && [ $index -lt ${#TASK_NAMES[@]} ]; then
echo "${TASK_NAMES[$index]}"
else
echo ""
fi
else
# Input is a task name, return as is
echo "$input"
fi
}
# Function to save current task
save_current_task() {
if [ ${#SOURCES_TO_BACKUP[@]} -eq 0 ]; then
echo "⚠️ No sources to save. Please add some paths first."
return 1
fi
read -p "Enter a name for this task: " task_name
# Remove invalid characters from task name
task_name=$(echo "$task_name" | tr -cd '[:alnum:]._-')
if [ -z "$task_name" ]; then
echo "❌ Invalid task name. Task not saved."
return 1
fi
local task_file="$TASKS_DIR/${task_name}.task"
# Save the sources to the task file
printf '%s\n' "${SOURCES_TO_BACKUP[@]}" > "$task_file"
if [ $? -eq 0 ]; then
echo "✅ Task '$task_name' saved successfully!"
echo " File: $task_file"
echo " Sources saved: ${#SOURCES_TO_BACKUP[@]}"
else
echo "❌ Error saving task '$task_name'."
return 1
fi
}
# Function to load a saved task
load_saved_task() {
if ! list_saved_tasks; then
return 1
fi
echo ""
read -p "Enter the task number or name to load (or press Enter to cancel): " user_input
if [ -z "$user_input" ]; then
echo "Operation cancelled."
return 1
fi
# Get the actual task name (handles both number and name input)
local task_name=$(get_task_name "$user_input")
if [ -z "$task_name" ]; then
echo "❌ Invalid selection. Please enter a valid number or task name."
return 1
fi
local task_file="$TASKS_DIR/${task_name}.task"
if [ ! -f "$task_file" ]; then
echo "❌ Task '$task_name' not found."
return 1
fi
# Clear existing sources
SOURCES_TO_BACKUP=()
# Load sources from file
while IFS= read -r line; do
if [ -n "$line" ]; then
if [ -e "$line" ]; then
SOURCES_TO_BACKUP+=("$line")
echo " ✓ Loaded: '$line'"
else
echo " ⚠️ Warning: '$line' no longer exists. Skipped."
fi
fi
done < "$task_file"
if [ ${#SOURCES_TO_BACKUP[@]} -gt 0 ]; then
echo "✅ Task '$task_name' loaded successfully!"
echo " Valid sources loaded: ${#SOURCES_TO_BACKUP[@]}"
## ==> MODIFIED SECTION: Store the loaded task name in a global variable <== ##
LOADED_TASK_NAME="$task_name"
return 0
else
echo "❌ No valid sources found in task '$task_name'."
return 1
fi
}
# Function to delete a saved task
delete_saved_task() {
if ! list_saved_tasks; then
return 1
fi
echo ""
read -p "Enter the task name to delete (or press Enter to cancel): " task_name
if [ -z "$task_name" ]; then
echo "Operation cancelled."
return 1
fi
local task_file="$TASKS_DIR/${task_name}.task"
if [ ! -f "$task_file" ]; then
echo "❌ Task '$task_name' not found."
return 1
fi
read -p "Are you sure you want to delete task '$task_name'? (y/N): " confirm
if [[ $confirm =~ ^[Yy]$ ]]; then
rm "$task_file"
if [ $? -eq 0 ]; then
echo "✅ Task '$task_name' deleted successfully."
else
echo "❌ Error deleting task '$task_name'."
return 1
fi
else
echo "Operation cancelled."
fi
}
# Function to show main menu
show_menu() {
echo ""
echo "==========================================="
echo " Interactive Backup Script Menu"
echo "==========================================="
echo "1. Add files/folders manually"
echo "2. Load saved task"
echo "3. List saved tasks"
echo "4. Save current task"
echo "5. Delete saved task"
echo "6. Show current sources"
echo "7. Start backup"
echo "8. Exit"
echo "==========================================="
}
# Function to show current sources
show_current_sources() {
if [ ${#SOURCES_TO_BACKUP[@]} -eq 0 ]; then
echo ">> No sources currently selected."
else
echo ">> Current sources to backup (${#SOURCES_TO_BACKUP[@]} items):"
for i in "${!SOURCES_TO_BACKUP[@]}"; do
echo " [$((i+1))] ${SOURCES_TO_BACKUP[i]}"
done
fi
}
# Function to add sources manually
add_sources_manually() {
echo ">> Please enter the full path for each file or folder you want to add."
echo ">> Press [ENTER] on an empty line when you are finished."
echo "------------------------------------------------------------------"
while true; do
read -p "Add path to backup (or press Enter to finish): " user_input
if [ -z "$user_input" ]; then
break
fi
if [ ! -e "$user_input" ]; then
echo " ⚠️ Warning: '$user_input' does not exist. It will be skipped."
continue
fi
# Check if already exists in array
local exists=false
for source in "${SOURCES_TO_BACKUP[@]}"; do
if [ "$source" = "$user_input" ]; then
exists=true
break
fi
done
if [ "$exists" = true ]; then
echo " ⚠️ Warning: '$user_input' already added. Skipped."
continue
fi
SOURCES_TO_BACKUP+=("$user_input")
echo " + Added: '$user_input'"
done
}
# --- MAIN SCRIPT LOGIC ---
## ==> NEW SECTION: Initialize variable to hold the loaded task name <== ##
SOURCES_TO_BACKUP=()
LOADED_TASK_NAME=""
echo "======================================================"
echo " Interactive Backup Script with Task Manager"
echo "======================================================"
# Main menu loop
while true; do
show_menu
read -p "Select an option (1-8): " choice
case $choice in
1)
add_sources_manually
;;
2)
# Call the function and check its exit status
if load_saved_task; then
# If the task loaded successfully, ask the user what to do next
echo ""
echo "What would you like to do next?"
echo " 1. Start backup immediately"
echo " 2. Return to menu (to modify sources)"
read -p "Select an option (1-2): " post_load_choice
if [[ "$post_load_choice" == "1" ]]; then
break # Exit the menu loop to proceed with the backup
fi
# Otherwise, do nothing and the loop will show the main menu again
fi
;;
3)
list_saved_tasks
;;
4)
save_current_task
;;
5)
delete_saved_task
;;
6)
show_current_sources
;;
7)
# Check if we have sources to backup
if [ ${#SOURCES_TO_BACKUP[@]} -eq 0 ]; then
echo "❌ No sources selected. Please add some files/folders or load a saved task first."
continue
fi
break # Exit menu loop and proceed with backup
;;
8)
echo "Goodbye!"
exit 0
;;
*)
echo "❌ Invalid option. Please select 1-8."
;;
esac
echo ""
read -p "Press Enter to continue..."
done
echo "------------------------------------------------------------------"
echo ">> Starting backup process..."
# Get the current date and time to create a unique filename
TIMESTAMP=$(date +"%Y-%m-%d_%H-%M-%S")
## ==> MODIFIED SECTION: Use task name in the filename if it's set <== ##
if [ -n "$LOADED_TASK_NAME" ]; then
BACKUP_FILENAME="${LOADED_TASK_NAME}-${TIMESTAMP}.tar.gz"
else
BACKUP_FILENAME="backup-${TIMESTAMP}.tar.gz"
fi
BACKUP_FILE="${DESTINATION_DIR}/${BACKUP_FILENAME}"
# Check if the destination directory exists. If not, create it.
if [ ! -d "$DESTINATION_DIR" ]; then
echo ">> Destination directory not found. Creating it: ${DESTINATION_DIR}"
mkdir -p "$DESTINATION_DIR"
if [ $? -ne 0 ]; then
echo " Error: Could not create destination directory. Aborting." >&2
exit 1
fi
fi
# Show final summary
echo ">> Backup Summary:"
echo " Sources to backup: ${#SOURCES_TO_BACKUP[@]} items"
for i in "${!SOURCES_TO_BACKUP[@]}"; do
echo " [$((i+1))] ${SOURCES_TO_BACKUP[i]}"
done
echo " Destination: ${BACKUP_FILE}"
echo ""
read -p "Proceed with backup? (Y/n): " confirm
if [[ $confirm =~ ^[Nn]$ ]]; then
echo "Backup cancelled."
exit 0
fi
# Create the compressed tar archive
echo ">> Starting backup of ${#SOURCES_TO_BACKUP[@]} items..."
tar -czvf "$BACKUP_FILE" "${SOURCES_TO_BACKUP[@]}"
# Verify that the backup was created successfully
if [ $? -eq 0 ]; then
echo "✅ Backup created successfully!"
echo " Archive: ${BACKUP_FILE}"
echo " Archive size: $(du -h "$BACKUP_FILE" | awk '{print $1}')"
# Ask if user wants to save this task
if [ ${#SOURCES_TO_BACKUP[@]} -gt 0 ]; then
echo ""
read -p "Would you like to save this backup configuration as a task? (y/N): " save_task
if [[ $save_task =~ ^[Yy]$ ]]; then
save_current_task
fi
fi
else
echo "❌ Error: Backup failed. Please check the output above for errors." >&2
exit 1
fi
exit 0