본문으로 건너뛰기

파일_Bash 노트 3

무료2017-03-19#Tool#linux文件权限#diff命令#vps硬盘测速#linux文件名空格

파일 관련 상식 및 자주 사용하는 명령 기록

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 매개변수에 fdatasyncfsync 옵션이 없습니다.

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

주의: st는 대소문자 두 가지가 있습니다. 소문자 sx 권한이 있음을, 대문자 Sx 권한이 없음을 나타냅니다.

권한 수정

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. 단어를 세는 기능은 다소 약합니다. 공백으로 구분된 문자열을 하나의 단어로 간주하며 문장 부호를 구분하지 않습니다.

댓글

아직 댓글이 없습니다

댓글 작성