UNIX 시스템은 모든 것을 파일로 간주합니다. 심지어 명령 터미널조차도 장치 파일과 연결되어 있으며, 해당 파일에 데이터를 씀으로써 터미널에 정보를 출력할 수 있습니다. 예를 들어:
# 현재 터미널에 출력
echo hoho > /dev/tty
# bash 환경에서 ttys001 포트에 연결된 터미널로 전송
echo hoho > /dev/ttys001
dd
지정된 크기의 파일을 생성하는 데 사용되며, 주로 하드 디스크 읽기/쓰기 속도 측정에 사용됩니다.
// 테스트 파일 test.data 생성
// \0으로 채우기, 크기는 10M
dd if=/dev/zero of=test.data bs=1024 count=10k
// 하드 디스크 쓰기 속도 측정
// 디스크에 연속 쓰기를 수행하며, 메모리 버퍼를 사용하지 않고 매번 8k 데이터를 씁니다. 총 4k번 수행하여 32M 크기의 파일을 생성합니다.
dd bs=8k count=4k if=/dev/zero of=test.data conv=fdatasync
// 하드 디스크 읽기 속도 측정
dd if=test.data of=/dev/null bs=4k
if는 입력 파일(input file), of는 출력 파일, bs는 쓰기 블록 크기를 나타냅니다. /dev/zero는 무한한 \0 문자를 생성하는 특수 장치이며, dev/null은 입력된 모든 데이터를 버리는 빈 장치입니다.
P.S. Mac 환경에서는 conv 매개변수에 fdatasync 및 fsync 옵션이 없습니다.
comm
comm 명령은 텍스트 파일을 비교하여 diff를 수행합니다. 단, 입력 파일은 반드시 정렬되어 있어야 하므로 일반적으로 sort와 함께 사용합니다:
# sort 명령의 -o 옵션은 파일로 출력을 의미하며, 여기서는 원본 파일을 직접 대체합니다.
sort a.txt -o a.txt; sort b.txt -o b.txt
# diff 수행
comm a.txt b.txt
P.S. wget의 -o- 옵션은 모양이 흥미로운데, Get as a file and print the result on STDOUT을 의미합니다.
결과는 다음과 같이 3개 열로 출력됩니다:
# a에는 있고 b에는 없는 것 | b에는 있고 a에는 없는 것 | a, b 모두에 있는 것
a-b 차집합 b-a 차집합 a∩b 교집합
이 3개 열을 이용하면 a 파일과 b 파일을 복구할 수 있습니다(정렬된 상태 기준이며, 정렬 전 상태로는 복구 불가). 예를 들어 a = (a-b) ∪ (a∩b)입니다.
-1/-2/-3 옵션은 지정된 열을 삭제하며, 옵션은 반드시 입력 파일 앞에 위치해야 합니다. 예를 들어:
# 3번째 열을 제거하여 a∩b를 출력하지 않음
comm -3 a.txt b.txt
# a, b의 차이점을 한 열로 병합하여 차이가 있는 행들만 출력
comm -3 a.txt b.txt | sed $'s/\t//g'
특별히 주의할 점: 정규 표현식 앞의 $ 기호는 값 평가 연산을 수행합니다. 이것이 없으면 탭(tab) 문자를 매칭할 수 없으며, IFS=$'\n'과 같은 원리입니다.
P.S. Mac 환경에서 sed -i를 사용한 파일 직접 수정은 다소 번거롭습니다. 반드시 백업 파일 이름을 지정해야 합니다(빈 문자열로 지정 가능).
diff
차이점 파일을 생성하는 데 사용됩니다. 예를 들어:
# -u 옵션은 더 일반적인 형식을 출력하며 ab.diff에 저장합니다.
diff -u a.txt b.txt > ab.diff
행 단위로 파일을 비교하여 추가된 행과 삭제된 행을 찾습니다(수정 작업은 새로운 행 추가와 기존 행 삭제의 조합으로 간주됨). 결과는 다음과 유사합니다:
--- a.txt 2017-03-15 10:50:34.000000000 +0800
+++ b.txt 2017-03-19 16:56:14.000000000 +0800
@@ -1,6 +1,11 @@
+
+end yaya
data
-end
is
-line
no
+line
this
+
+newend
+line
diff 결과를 사용해 a와 b에 패치를 적용하면 각각 b와 a를 얻을 수 있습니다:
# a에 패치 적용
patch -p1 a.txt < ab.diff
# a와 b의 내용이 동일함
md5 a.txt; md5 b.txt
원본 내용을 복구하려면 patch를 한 번 더 실행합니다:
# 패치 되돌리기
patch -p1 a.txt < ab.diff
폴더에 대해서도 diff를 수행할 수 있습니다:
# N은 존재하지 않는 파일을 빈 파일로 간주, a는 모든 파일을 텍스트 파일로 간주, r은 하위 디렉터리를 재귀적으로 비교함
diff -Naur data files
mkdir
폴더를 생성하는 데 사용됩니다. 이미 존재하는 경우 오류를 반환합니다:
mkdir: bak: File exists
일반적으로 다음과 같은 확인이 필요합니다:
# 존재하지 않는 경우에만 생성
if [ ! -e path ]; then mkdir $path; fi
깊은 경로의 경우 단계별로 확인하는 것이 번거로우므로 단순히 오류를 무시할 수 있습니다:
mkdir ./dir1 2>/dev/null
mkdir ./dir1/dir2 2>/dev/null
mkdir ./dir1/dir2/dir3 2>/dev/null
더 간단한 방법은 다음과 같습니다:
mkdir -p ./dir1/dir2/dir3
이미 존재하는 것은 무시하고 생성해야 할 디렉터리만 생성합니다.
파일 권한
일반적인 3가지 권한 유형:
-
user: 파일 소유자(owner)
-
group: 사용자 그룹
-
others: user와 group 이외의 사용자
ls -l 명령으로 나열되는 파일 권한 형식은 다음과 같습니다: 파일 유형(1자리) user 권한(3자리) group 권한(3자리) others 권한(3자리)
파일 유형은 다음과 같습니다:
- 일반 파일
d 디렉터리
c 문자 장치
b 블록 장치
l 심볼릭 링크
s 소켓
p 파이프
뒤따르는 3자리 권한의 각 자리 값은 4가지가 있습니다: -rwx는 각각 없음/읽기/쓰기/실행을 나타냅니다.
P.S. 파일 권한이 ----------라면 root를 제외한 모든 사용자가 해당 파일을 처리할 권한이 없음을 의미하며 읽기, 쓰기, 실행이 불가능합니다.
또한 x 위치에 나타날 수 있는 3가지 특수 권한이 있습니다:
-
setuid: 사용자가 소유자(owner) 권한으로 파일을 실행할 수 있게 함. 예:
-rws------ -
setgid: 사용자가 그룹 권한으로 파일을 실행할 수 있게 함. 예:
----rws--- -
sticky bit: 해당 디렉터리를 생성한 사용자만 하위 파일을 삭제할 권한을 가짐. 다른 사용자는 쓰기 권한이 있더라도 삭제 불가. 예:
-------rwt
주의: s와 t는 대소문자 두 가지가 있습니다. 소문자 s는 x 권한이 있음을, 대문자 S는 x 권한이 없음을 나타냅니다.
권한 수정
chmod 명령을 사용합니다. 예를 들어:
# 권한 설정
chmod u=rwx g=rwx o=rwx test.sh
# user 실행 권한 추가
chmod u+x test.sh
# 모든 실행 권한 추가
chmod a+x test.sh
# user 권한 삭제
chmod u-x test.sh
숫자 값으로 권한을 설정할 수도 있습니다:
# u=rwx g=rwx o=rwx와 동일함
chmod 777 test.sh
777은 세 그룹의 rwx 이진 표현에 대응하는 십진수입니다. 예를 들어 r--는 4(100)입니다.
P.S. 보통 이를 8진수 값이라고 부르지만, 실제로는 2진수로 해석하는 것이 더 합리적입니다.
3가지 특수 권한 설정도 chmod를 사용합니다:
# setuid, setgid, sticky bit
chmod u+s
chmod g+s
chmod o+t
숫자로 설정할 경우 3가지 권한 앞에 sst 그룹을 추가합니다. 예를 들어 chmod 2777 test.sh에서 특수 권한은 2(010)이며, 이는 -s- 즉 setgid 권한을 나타냅니다.
소유권을 수정하는 명령은 chown입니다:
# user1 사용자 및 staff 그룹 소유로 설정
chown user1.staff test.sh
일반적으로 setuid 권한과 함께 사용됩니다:
# root 그룹 root 사용자
chown root.root bomb.sh
# 소유자 권한 실행 설정 (마치 왕이 친히 임한 것처럼)
chown u+s bomb.sh
touch
touch는 파일을 건드려 존재하면 타임스탬프를 업데이트하고, 존재하지 않으면 빈 파일을 생성합니다:
# 존재하는 경우 모든 타임스탬프를 현재 시간으로 업데이트
touch test.sh
# 존재하는 경우 액세스 시간만 업데이트
touch -a test.sh
# 존재하는 경우 수정 시간만 업데이트
touch -m test.sh
head/tail
파일 내용의 특정 부분만 확인합니다. 예를 들어:
# 앞의 10행 확인
head test.sh
# 앞의 3행 확인
head -n 3 test.sh
# 뒤의 10행을 제외하고 출력
head -n -10 test.sh
# 뒤의 10행 확인
tail test.sh
# 뒤의 3행 확인
tail -n 3 test.sh
# 앞의 90행을 제외하고 확인 (91행부터 끝까지 출력)
seq 100 | tail -n +91
P.S. Mac 환경에서는 -n 매개변수에 음수를 사용할 수 없으며 head: illegal line count -- -10 오류가 발생합니다.
ls 명령으로 디렉터리만 나열하기
3가지 방법이 있습니다:
# -d 옵션이 가장 간결함
ls -d */
# -F로 유형 식별자를 붙이고 /로 끝나는 것을 필터링
ls -F | grep "/$"
# -l 옵션 결과는 권한으로 시작하고 권한은 유형으로 시작하므로 d로 시작하는 것을 필터링
ls -l | grep "^d" | awk '{print $9"/"}'
find를 사용할 수도 있습니다:
# 파일 유형별 찾기
find . -type d -maxdepth 1 -mindepth 1 -print
depth 범위에 주의하세요. 바로 아래 단계만 찾습니다.
경로 전환
보통 cd -(cd $OLDPWD)를 사용하여 이전 작업 경로로 돌아가지만, 사실 더 강력한 기능이 있습니다:
# cd와 역할이 같아 보임
pushd /tmp
# 과거 경로 스택 확인 (-v는 번호 표시)
dirs -v
# 이전 작업 경로로 복귀
pushd
# 전전 작업 경로로 복귀...
pushd +1
# 그 전 작업 경로로 복귀...
pushd +2
pushd는 작업 경로를 전환하고 스택 최상단 기록을 지정된 기록과 교체하지만, 히스토리 스택 길이는 변하지 않습니다. 기록을 삭제하려면 popd를 사용합니다:
# 이전 작업 경로로 복귀하고 현재 경로 삭제
popd
# 전전 작업 경로 삭제
popd +1
# 히스토리 스택 비우기 (현재 기록만 유지)
dirs -c
+N, -N은 방향을 나타내며, +N은 스택 상단부터 0123...으로 세고, -N은 스택 하단부터 셉니다.
P.S. oh my zsh의 특정 버전에서는 +- 방향이 반대인 경우가 있으니 주의하세요. bash는 정상입니다.
wc
행 수, 단어 수, 문자 수를 집계하며 간단한 코드 통계에 자주 사용됩니다:
# 행 수, 단어 수, 문자 수 출력
wc test.sh
# 행 수 가져오기
wc -l test.sh | awk '{print $1}'
# 단어 수 가져오기
wc -w test.sh | awk '{print $1}'
# 문자 수 가져오기
wc -c test.sh | awk '{print $1}'
P.S. 단어를 세는 기능은 다소 약합니다. 공백으로 구분된 문자열을 하나의 단어로 간주하며 문장 부호를 구분하지 않습니다.
아직 댓글이 없습니다