Bash - 본 어게인 셸
Bash (본 어게인 셸)는 GNU 프로젝트를 위해 Brian Fox가 작성한 Unix 셸과 명령어 언어로, Bourne 셸의 무료 소프트웨어 대체품입니다. 1989년에 처음 출시된 Bash는 대부분의 Linux 배포판에서 기본 셸이 되었으며, Unix/Linux 생태계에서 가장 널리 사용되는 셸 중 하나입니다. 원래의 Bourne 셸의 기능과 함께 명령어 완성, 명령어 히스토리, 개선된 스크립팅 기능 등 추가 기능을 결합했습니다.
설치 및 설정
Bash 설치 확인
Bash를 기본 셸로 설정
다른 시스템에서의 Bash 설치
Bash 기본 문법과 명령어
명령어 구조
변수 및 환경
명령어 치환
인용 및 이스케이프
파일 작업 및 탐색
디렉토리 탐색
파일 및 디렉토리 목록
파일 작업
파일 권한 및 소유권
텍스트 처리 및 조작
파일 내용 작업
텍스트 검색 및 필터링
텍스트 처리 도구
입력/출력 리다이렉션 및 파이프
리다이렉션 연산자
파이프 및 명령어 체이닝
프로세스 관리
작업 제어
프로세스 정보
Bash 스크립팅 기본
스크립트 구조
Note: Since some sections were empty in the original text, I’ve left them as empty in the translation as well. If you want me to fill those with typical content, please let me know.```bash
Check if Bash is installed
which bash /bin/bash
Check Bash version
bash —version GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)
Check current shell
echo $SHELL /bin/bash
Check available shells
cat /etc/shells
### Setting Bash as Default Shell
```bash
# Set Bash as default shell for current user
chsh -s /bin/bash
# Set Bash as default shell for specific user (as root)
sudo chsh -s /bin/bash username
# Verify shell change
echo $SHELL
Bash Installation on Different Systems
# Ubuntu/Debian
sudo apt update && sudo apt install bash
# CentOS/RHEL/Fedora
sudo dnf install bash
# macOS (using Homebrew for latest version)
brew install bash
# Arch Linux
sudo pacman -S bash
# FreeBSD
pkg install bash
Basic Bash Syntax and Commands
Command Structure
# Basic command structure
command [options] [arguments]
# Examples
ls -la /home
cp file1.txt file2.txt
grep -r "pattern" /path/to/search
Variables and Environment
# Variable assignment (no spaces around =)
name="John Doe"
age=30
path="/home/user"
# Using variables
echo $name
echo $\\\\{name\\\\}
echo "Hello, $name"
# Environment variables
export PATH="/usr/local/bin:$PATH"
export EDITOR="vim"
# Special variables
echo $0 # Script name
echo $1 # First argument
echo $# # Number of arguments
echo $@ # All arguments
echo $ # Process ID
echo $? # Exit status of last command
Command Substitution
# Using $() (preferred)
current_date=$(date)
file_count=$(ls|wc -l)
user_home=$(eval echo ~$USER)
# Using backticks (legacy)
current_date=`date`
file_count=`ls|wc -l`
# Nested command substitution
echo "Today is $(date +%A), $(date +%B) $(date +%d)"
Quoting and Escaping
# Single quotes (literal)
echo 'The variable $HOME is not expanded'
# Double quotes (variable expansion)
echo "Your home directory is $HOME"
# Escaping special characters
echo "The price is \$10"
echo "Use \"quotes\" inside quotes"
# Here documents
cat << EOF
This is a multi-line
text block that can contain
variables like $HOME
EOF
# Here strings
grep "pattern" <<< "$variable"
File Operations and Navigation
Directory Navigation
# Change directory
cd /path/to/directory
cd ~ # Home directory
cd - # Previous directory
cd .. # Parent directory
cd ../.. # Two levels up
# Print working directory
pwd
# Directory stack operations
pushd /path/to/dir # Push directory onto stack
popd # Pop directory from stack
dirs # Show directory stack
File and Directory Listing
# Basic listing
ls
ls -l # Long format
ls -la # Long format with hidden files
ls -lh # Human readable sizes
ls -lt # Sort by modification time
ls -lS # Sort by size
ls -lR # Recursive listing
# Advanced listing options
ls -la --color=auto # Colored output
ls -la --time-style=full-iso # ISO time format
ls -la --group-directories-first # Directories first
File Operations
# Create files
touch file.txt
touch file1.txt file2.txt file3.txt
# Copy files and directories
cp source.txt destination.txt
cp -r source_dir/ destination_dir/
cp -p file.txt backup.txt # Preserve attributes
cp -u source.txt dest.txt # Update only if newer
# Move and rename
mv old_name.txt new_name.txt
mv file.txt /path/to/destination/
mv *.txt /path/to/directory/
# Remove files and directories
rm file.txt
rm -f file.txt # Force removal
rm -r directory/ # Recursive removal
rm -rf directory/ # Force recursive removal
rm -i *.txt # Interactive removal
# Create directories
mkdir directory_name
mkdir -p path/to/nested/directory
mkdir -m 755 directory_name # With specific permissions
File Permissions and Ownership
# Change permissions
chmod 755 file.txt
chmod u+x script.sh # Add execute for user
chmod g-w file.txt # Remove write for group
chmod o=r file.txt # Set read-only for others
chmod -R 644 directory/ # Recursive permission change
# Change ownership
chown user:group file.txt
chown -R user:group directory/
chgrp group file.txt # Change group only
# View permissions
ls -l file.txt
stat file.txt # Detailed file information
Text Processing and Manipulation
File Content Operations
# View file contents
cat file.txt # Display entire file
less file.txt # Paginated view
more file.txt # Simple paginated view
head file.txt # First 10 lines
head -n 20 file.txt # First 20 lines
tail file.txt # Last 10 lines
tail -n 20 file.txt # Last 20 lines
tail -f file.txt # Follow file changes
# File comparison
diff file1.txt file2.txt
diff -u file1.txt file2.txt # Unified format
cmp file1.txt file2.txt # Binary comparison
Text Search and Filtering
# grep - pattern searching
grep "pattern" file.txt
grep -i "pattern" file.txt # Case insensitive
grep -r "pattern" directory/ # Recursive search
grep -n "pattern" file.txt # Show line numbers
grep -v "pattern" file.txt # Invert match
grep -E "pattern1|pattern2" file.txt # Extended regex
# Advanced grep options
grep -A 3 "pattern" file.txt # Show 3 lines after match
grep -B 3 "pattern" file.txt # Show 3 lines before match
grep -C 3 "pattern" file.txt # Show 3 lines around match
grep -l "pattern" *.txt # Show only filenames
grep -c "pattern" file.txt # Count matches
Text Processing Tools
# sed - stream editor
sed 's/old/new/' file.txt # Replace first occurrence
sed 's/old/new/g' file.txt # Replace all occurrences
sed '1,5s/old/new/g' file.txt # Replace in lines 1-5
sed '/pattern/d' file.txt # Delete lines matching pattern
sed -n '1,10p' file.txt # Print lines 1-10
# awk - pattern scanning and processing
awk '\\\\{print $1\\\\}' file.txt # Print first column
awk '\\\\{print $NF\\\\}' file.txt # Print last column
awk '/pattern/ \\\\{print $0\\\\}' file.txt # Print lines matching pattern
awk -F: '\\\\{print $1\\\\}' /etc/passwd # Use : as field separator
awk '\\\\{sum += $1\\\\} END \\\\{print sum\\\\}' file.txt # Sum first column
# cut - extract columns
cut -d: -f1 /etc/passwd # Extract first field
cut -c1-10 file.txt # Extract characters 1-10
cut -f2,4 file.txt # Extract fields 2 and 4
# sort and uniq
sort file.txt # Sort lines
sort -n file.txt # Numeric sort
sort -r file.txt # Reverse sort
sort -k2 file.txt # Sort by second field
uniq file.txt # Remove duplicate lines
sort file.txt|uniq -c # Count occurrences
Input/Output Redirection and Pipes
Redirection Operators
# Output redirection
command > file.txt # Redirect stdout to file (overwrite)
command >> file.txt # Redirect stdout to file (append)
command 2> error.log # Redirect stderr to file
command 2>> error.log # Redirect stderr to file (append)
command &> output.log # Redirect both stdout and stderr
command > output.log 2>&1 # Redirect both stdout and stderr
# Input redirection
command < input.txt # Read input from file
command << EOF # Here document
line 1
line 2
EOF
# Advanced redirection
command 3> file.txt # Redirect to file descriptor 3
exec 3> file.txt # Open file descriptor 3
echo "text" >&3 # Write to file descriptor 3
exec 3>&- # Close file descriptor 3
Pipes and Command Chaining
# Basic pipes
ls -l|grep "txt" # List files and filter for .txt
ps aux|grep "process_name" # Show processes and filter
cat file.txt|sort|uniq # Sort and remove duplicates
# Complex pipe chains
cat /var/log/access.log|grep "404"|awk '\\\\{print $1\\\\}'|sort|uniq -c|sort -nr
find . -name "*.log"|xargs grep "ERROR"|cut -d: -f1|sort|uniq
# Tee command (split output)
command|tee file.txt # Write to file and stdout
command|tee -a file.txt # Append to file and stdout
Process Management
Job Control
# Background and foreground jobs
command & # Run command in background
jobs # List active jobs
fg %1 # Bring job 1 to foreground
bg %1 # Send job 1 to background
kill %1 # Kill job 1
# Process control signals
Ctrl+C # Interrupt (SIGINT)
Ctrl+Z # Suspend (SIGTSTP)
Ctrl+\ # Quit (SIGQUIT)
Process Information
# Process listing
ps # Show current processes
ps aux # Show all processes
ps -ef # Full format listing
pstree # Show process tree
top # Real-time process monitor
htop # Enhanced process monitor
# Process management
kill PID # Terminate process
kill -9 PID # Force kill process
killall process_name # Kill all processes by name
pkill pattern # Kill processes matching pattern
nohup command & # Run command immune to hangups
Bash Scripting Fundamentals
Script Structure
#!/bin/bash
# Script description and metadata
# Author: Your Name
# Date: YYYY-MM-DD
# Version: 1.0
# Script content starts here
echo "Hello, World!"
```### 변수와 데이터 타입
```bash
# String variables
name="John Doe"
message='Hello, World!'
multiline="This is a
multi-line string"
# Numeric variables
number=42
pi=3.14159
# Arrays
fruits=("apple" "banana" "orange")
numbers=(1 2 3 4 5)
# Associative arrays (Bash 4+)
declare -A colors
colors[red]="#FF0000"
colors[green]="#00FF00"
colors[blue]="#0000FF"
# Array operations
echo $\\\\{fruits[0]\\\\} # First element
echo $\\\\{fruits[@]\\\\} # All elements
echo $\\\\{#fruits[@]\\\\} # Array length
fruits+=("grape") # Append element
```### 조건문
```bash
# if-then-else
if [ condition ]; then
echo "Condition is true"
elif [ other_condition ]; then
echo "Other condition is true"
else
echo "No condition is true"
fi
# Test conditions
if [ "$var" = "value" ]; then # String equality
if [ "$num" -eq 10 ]; then # Numeric equality
if [ "$num" -gt 5 ]; then # Greater than
if [ "$num" -lt 20 ]; then # Less than
if [ -f "file.txt" ]; then # File exists
if [ -d "directory" ]; then # Directory exists
if [ -r "file.txt" ]; then # File is readable
if [ -w "file.txt" ]; then # File is writable
if [ -x "script.sh" ]; then # File is executable
# Logical operators
if [ condition1 ] && [ condition2 ]; then # AND
if [ condition1 ]||[ condition2 ]; then # OR
if [ ! condition ]; then # NOT
# Case statement
case $variable in
pattern1)
echo "Matched pattern1"
;;
pattern2|pattern3)
echo "Matched pattern2 or pattern3"
;;
*)
echo "No pattern matched"
;;
esac
```### 반복문
```bash
# for loop
for i in \\\\{1..10\\\\}; do
echo "Number: $i"
done
for file in *.txt; do
echo "Processing: $file"
done
for item in "$\\\\{array[@]\\\\}"; do
echo "Item: $item"
done
# C-style for loop
for ((i=1; i<=10; i++)); do
echo "Counter: $i"
done
# while loop
counter=1
while [ $counter -le 10 ]; do
echo "Counter: $counter"
((counter++))
done
# until loop
counter=1
until [ $counter -gt 10 ]; do
echo "Counter: $counter"
((counter++))
done
# Loop control
for i in \\\\{1..10\\\\}; do
if [ $i -eq 5 ]; then
continue # Skip iteration
fi
if [ $i -eq 8 ]; then
break # Exit loop
fi
echo $i
done
```### 함수
```bash
# Function definition
function greet() \\\\{
echo "Hello, $1!"
\\\\}
# Alternative syntax
greet() \\\\{
echo "Hello, $1!"
\\\\}
# Function with return value
calculate_sum() \\\\{
local num1=$1
local num2=$2
local sum=$((num1 + num2))
echo $sum
\\\\}
# Function with local variables
process_file() \\\\{
local filename=$1
local line_count=$(wc -l < "$filename")
echo "File $filename has $line_count lines"
\\\\}
# Function usage
greet "World"
result=$(calculate_sum 5 3)
echo "Sum: $result"
```## 고급 Bash 기능
```bash
# Basic parameter expansion
echo $\\\\{variable\\\\}
echo $\\\\{variable:-default\\\\} # Use default if unset
echo $\\\\{variable:=default\\\\} # Set default if unset
echo $\\\\{variable:+alternate\\\\} # Use alternate if set
echo $\\\\{variable:?error\\\\} # Error if unset
# String manipulation
string="Hello, World!"
echo $\\\\{string#Hello\\\\} # Remove shortest match from beginning
echo $\\\\{string##*/\\\\} # Remove longest match from beginning
echo $\\\\{string%World!\\\\} # Remove shortest match from end
echo $\\\\{string%%/*\\\\} # Remove longest match from end
echo $\\\\{string/Hello/Hi\\\\} # Replace first occurrence
echo $\\\\{string//l/L\\\\} # Replace all occurrences
# Substring extraction
echo $\\\\{string:0:5\\\\} # Extract substring (position:length)
echo $\\\\{string:7\\\\} # Extract from position to end
echo $\\\\{#string\\\\} # String length
```### 매개변수 확장
```bash
# Arithmetic expansion
result=$((5 + 3))
result=$((10 * 2))
result=$((20 / 4))
result=$((17 % 5)) # Modulo
# Increment/decrement
((counter++))
((counter--))
((counter += 5))
((counter -= 3))
# Arithmetic with variables
num1=10
num2=5
sum=$((num1 + num2))
product=$((num1 * num2))
# Floating point arithmetic (using bc)
result=$(echo "scale=2; 10/3"|bc)
result=$(echo "scale=4; sqrt(16)"|bc -l)
```### 산술 연산
```bash
# Exit on error
set -e # Exit on any error
set -u # Exit on undefined variable
set -o pipefail # Exit on pipe failure
# Error handling in scripts
command||\\\\{
echo "Command failed"
exit 1
\\\\}
# Trap signals
trap 'echo "Script interrupted"; exit 1' INT TERM
trap 'cleanup_function' EXIT
# Function error handling
safe_command() \\\\{
if ! command_that_might_fail; then
echo "Error: Command failed" >&2
return 1
fi
\\\\}
```### 오류 처리
```bash
# System-wide configuration
/etc/bash.bashrc # System-wide bashrc
/etc/profile # System-wide profile
# User-specific configuration
~/.bashrc # User's bashrc
~/.bash_profile # User's profile
~/.bash_login # Login shell configuration
~/.profile # POSIX shell profile
~/.bash_logout # Logout script
```## 구성 및 사용자 정의
```bash
# ~/.bashrc example configuration
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
# User specific environment
export EDITOR="vim"
export BROWSER="firefox"
export PAGER="less"
# Custom PATH
export PATH="$HOME/bin:$HOME/.local/bin:$PATH"
# Aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
# Custom functions
mkcd() \\\\{
mkdir -p "$1" && cd "$1"
\\\\}
extract() \\\\{
if [ -f $1 ] ; then
case $1 in
*.tar.bz2) tar xjf $1 ;;
*.tar.gz) tar xzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar e $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xf $1 ;;
*.tbz2) tar xjf $1 ;;
*.tgz) tar xzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "'$1' cannot be extracted via extract()" ;;
esac
else
echo "'$1' is not a valid file"
fi
\\\\}
# Prompt customization
PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
# History configuration
HISTSIZE=10000
HISTFILESIZE=20000
HISTCONTROL=ignoredups:ignorespace
shopt -s histappend
# Shell options
shopt -s checkwinsize
shopt -s globstar
shopt -s cdspell
```### Bash 구성 파일
```bash
# Set options
set -o vi # Vi editing mode
set -o emacs # Emacs editing mode (default)
set -o noclobber # Prevent file overwriting
set +o noclobber # Allow file overwriting
# Shopt options
shopt -s autocd # Auto cd to directory
shopt -s cdspell # Correct minor spelling errors
shopt -s checkwinsize # Update LINES and COLUMNS
shopt -s cmdhist # Save multi-line commands
shopt -s dotglob # Include hidden files in globbing
shopt -s expand_aliases # Expand aliases
shopt -s extglob # Extended globbing
shopt -s globstar # ** recursive globbing
shopt -s histappend # Append to history file
shopt -s nocaseglob # Case-insensitive globbing
```### .bashrc 사용자 정의
```bash
# Emacs mode (default)
Ctrl+A # Beginning of line
Ctrl+E # End of line
Ctrl+B # Back one character
Ctrl+F # Forward one character
Alt+B # Back one word
Alt+F # Forward one word
Ctrl+D # Delete character
Ctrl+H # Backspace
Ctrl+K # Kill to end of line
Ctrl+U # Kill to beginning of line
Ctrl+W # Kill previous word
Alt+D # Kill next word
Ctrl+Y # Yank (paste)
Ctrl+T # Transpose characters
Alt+T # Transpose words
# Vi mode
set -o vi
Esc # Enter command mode
i # Insert mode
a # Append mode
A # Append at end of line
I # Insert at beginning of line
```### Bash 옵션 및 설정
```bash
# History commands
history # Show command history
history 10 # Show last 10 commands
history -c # Clear history
history -d 5 # Delete history entry 5
# History expansion
!! # Previous command
!n # Command number n
!string # Last command starting with string
!?string # Last command containing string
^old^new # Replace old with new in previous command
# History search
Ctrl+R # Reverse search
Ctrl+S # Forward search
Ctrl+G # Cancel search
# History configuration
export HISTSIZE=10000 # Commands in memory
export HISTFILESIZE=20000 # Commands in file
export HISTCONTROL=ignoredups # Ignore duplicates
export HISTIGNORE="ls:ll:cd:pwd:bg:fg:history" # Ignore commands
export HISTTIMEFORMAT="%F %T " # Add timestamps
```## 명령줄 편집 및 히스토리
```bash
# Debug modes
bash -x script.sh # Execute with trace
bash -n script.sh # Check syntax without execution
bash -v script.sh # Verbose mode
# Debug options in script
set -x # Enable trace
set +x # Disable trace
set -v # Enable verbose
set +v # Disable verbose
# Conditional debugging
if [ "$DEBUG" = "1" ]; then
set -x
fi
# Debug function
debug() \\\\{
if [ "$DEBUG" = "1" ]; then
echo "DEBUG: $*" >&2
fi
\\\\}
```### 명령줄 편집
```bash
# Check command success
if command; then
echo "Command succeeded"
else
echo "Command failed"
fi
# Check exit status
command
if [ $? -eq 0 ]; then
echo "Success"
else
echo "Failed with exit code $?"
fi
# Validate input
if [ $# -ne 2 ]; then
echo "Usage: $0 <arg1> <arg2>"
exit 1
fi
# Check file existence
if [ ! -f "$filename" ]; then
echo "Error: File $filename does not exist"
exit 1
fi
```### 히스토리 관리
```bash
# Time command execution
time command
time \\\\{ command1; command2; \\\\}
# Profile script execution
PS4='+ $(date "+%s.%N"): '
set -x
# Your commands here
set +x
# Memory usage
/usr/bin/time -v command
# Disk usage
du -sh directory/
df -h
```## 디버깅 및 문제 해결
```bash
# Use full paths for commands
/bin/ls instead of ls
/usr/bin/find instead of find
# Validate input
case "$input" in
[a-zA-Z0-9]*)
# Valid input
;;
*)
echo "Invalid input"
exit 1
;;
esac
# Quote variables
rm "$filename" # Correct
rm $filename # Dangerous
# Use arrays for file lists
files=( *.txt )
for file in "$\\\\{files[@]\\\\}"; do
process "$file"
done
```### 스크립트 디버깅
```bash
# Use built-in commands when possible
[[ condition ]] # Instead of [ condition ]
(( arithmetic )) # Instead of [ arithmetic ]
# Avoid unnecessary subshells
var=$(cat file) # Subshell
var=$(<file) # Built-in
# Use parameter expansion
$\\\\{var#pattern\\\\} # Instead of sed/awk for simple operations
$\\\\{var%pattern\\\\}
$\\\\{var/pattern/replacement\\\\}
# Efficient loops
while IFS= read -r line; do # Read file line by line
process "$line"
done < file.txt
```### 오류 검사
```bash
# Use functions for repeated code
log_message() \\\\{
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
\\\\}
# Separate configuration
CONFIG_FILE="$\\\\{HOME\\\\}/.myapp.conf"
if [ -f "$CONFIG_FILE" ]; then
source "$CONFIG_FILE"
fi
# Use meaningful variable names
user_count=10 # Good
uc=10 # Poor
# Comment complex logic
# Calculate the number of days between two dates
start_date=$(date -d "$1" +%s)
end_date=$(date -d "$2" +%s)
days=$(( (end_date - start_date) / 86400 ))
```### 성능 모니터링