cat(concatenate)
파일 내용을 읽고, 표시하고, 이어 붙입니다.
표준 입력으로부터 오는 내용과 파일 내용을 이어 붙이는 방법:
echo 'from stdin' | cat - test.sh
cat 명령에서 -는 표준 입력을 나타냅니다.
If file is a single dash (`-') or absent, cat reads from the standard input.
기타 자주 사용하는 기능 옵션:
# 파일 내용에 행 번호 붙이기
cat -n test.sh
# 파일 내 연속된 여러 빈 줄을 하나로 압축하기
cat -s test.sh
find
기본 규칙
파일 디렉터리를 하위로 탐색하며 조건에 맞는 파일을 찾아 처리합니다.
# 현재 디렉터리의 모든 파일/폴더, 하위 파일/폴더 나열
find .
# \0으로 구분 (파일 경로에 줄바꿈 문자가 있을 때 유용)
find . -print0
# 와일드카드
find -name "*.js"
# 대소문자 무시
find -iname "*.js"
# 다중 조건
find . \( -name "e*" -o -name "s*" \)
# 경로 매칭
find ../tnode -path "*node*"
# -path와 같으나 매개변수로 정규 표현식 사용
find . -regex ".*/e.*h$"
# 대소문자 무시 정규 표현식
find . -iregex ".*/e.*h$"
# 부정 매개변수 (단독 매개변수, -name/path/regex 등과 함께 사용 가능)
find . ! -iregex ".*/e.*h$"
# 예: 경로에 node_modules가 포함된 것 제외
find ../tnode ! -regex ".*node_modules.*"
# 디렉터리 깊이 지정, -maxdepth 1은 하위 1단계까지만 탐색 (부모의 자식까지만 찾고 손자는 찾지 않음)
find .. -name "*.js" -maxdepth 1
# 시작 깊이 지정 가능, -mindepth 2 -maxdepth 2는 손자 단계에서만 탐색
find .. -name "*.js" -mindepth 2 -maxdepth 2
# 지정된 깊이보다 깊은 파일만 찾기 (깊은 경로의 lib 찾기)
find .. -regex ".*node_modules*.*.js$" -mindepth 20
파일 유형별 검색
# 파일/폴더 지정, -type f는 파일만 출력
find ../tnode ! -regex ".*node_modules.*" -type f
P.S. 매개변수 순서가 검색 효율에 영향을 줍니다. 예를 들어 깊이를 먼저 확인한 후 유형을 필터링하는 것이 더 빠릅니다.
파일 유형과 type 매개변수 값 대응 관계:
일반 파일: f
심볼릭 링크: l
디렉터리: d
문자 장치 파일: c
블록 장치 파일: b
소켓: s
FIFO: p
시간별 검색
각 파일에는 3가지 타임스탬프가 있습니다:
액세스 시간: -atime
수정 시간: -mtime
상태 변경 시간: -ctime
매개변수 값은 정수(일 단위)이며, +와 - 접두사를 통해 각각 크다, 작다를 표현할 수 있습니다. 예:
# 상위 디렉터리에서 어제부터 지금까지 액세스된 파일 찾기
find .. -type f -atime -1
분 단위 옵션도 있습니다:
# -amin, -mmin, -cmin
find .. -type f -amin $((-1 * 60 * 24))
특정 파일을 기준으로 그보다 더 최신인(수정 시간이 더 가까운) 파일을 찾을 수도 있습니다:
# 상위 디렉터리에서 ~/.bash_profile보다 최신인 파일 찾기
find .. -type f -newer ~/.bash_profile
파일 크기별 검색
# 현재 디렉터리에서 1K보다 큰 파일 찾기
find . -type f -size +1k
b(블록), c(바이트), w(워드), k, M, G 단위를 지원합니다. 앞의 네 개는 소문자, 뒤의 두 개는 대문자임에 주의하세요. split 등 다른 명령에서도 보통 이와 같습니다.
기타 용법
# 찾아서 삭제
find . -type f -name "*.tmp" -delete
# 파일 권한 매칭
find . -type f -perm 777 -print
find . -type f -user ayqy
-exec와 결합하여 다른 명령 실행
# 찾아서 형식에 맞춰 출력
find . -type f -exec printf "file: %s\n" {} \;
# 찾아서 백업
find . -type f -mtime +7 -exec cp {} bak/ \;
P.S. 마지막의 이스케이프된 세미콜론은 -exec 매개변수의 끝을 나타내며 반드시 필요합니다.
-exec는 하나의 명령만 실행할 수 있습니다. 여러 명령을 실행해야 한다면 파일에 기록한 뒤 실행하세요. 예: bak.sh에 백업 명령 기록
#!/bin/bash
BAK_DIR=bak
if ! test -e "$BAK_DIR";
then
mkdir "$BAK_DIR"
fi
for file in "$@";
do
cp $file "$BAK_DIR"
done
그 후 찾아서 실행:
find . -type f -mtime +7 -exec ./bak.sh {} \;
-prune으로 검색에서 제외할 항목 지정:
# .git과 node_modules 디렉터리 건너뛰기
find . \( -name ".git" -prune \) -o \( -name "node_modules" -prune \) -o \( -type f -print \)
xargs
xargs 명령은 stdin으로부터 받은 데이터를 재포맷하여 다른 명령의 인자로 제공합니다. 파이프 연산자 바로 뒤에 오며 기본 형식은 다음과 같습니다:
cmd | xargs
여러 줄의 입력을 한 줄의 출력으로 변환:
# 줄바꿈 문자를 공백으로 변경
cat test.sh | xargs
한 줄의 입력을 여러 줄의 출력으로 변환:
# 각 행당 인자 개수 지정
echo "1 22 3 4 5 6 7" | xargs -n 3
-d로 구분자 지정하여 문자열 split 구현:
# split
echo "1,2,3,4" | xargs -d ,
# `-d` 매개변수는 GNU 확장으로, FreeBSD나 Mac에는 없을 수 있습니다. 다른 방법을 사용하세요.
echo "1,2,3,4" | tr , ' '
-I로 대체 문자열 지정:
# replace
echo "1 2 3 4" | xargs -n 1 -I {} find {}.txt
find와 xargs 결합:
# 찾아서 삭제
find . -type f -name "*.tmp" -print0 | xargs -0 rm -f
여기서 -print0과 xargs -0은 \0을 구분자로 사용하여 temp file.tmp와 같이 공백이 포함된 파일명이 두 개의 인자로 쪼개지는 것을 방지합니다.
코드 라인 수 집계:
find . -type f -name "*.sh" -print0 | xargs -0 wc -l
하나의 인자에 대해 여러 명령 실행:
# 위에서의 replace와 동일한 역할
echo '1\n2\n3\n4' | (while read arg; do find $arg.txt; done)
xargs는 각 인자당 하나의 명령만 실행할 수 있지만, 서브쉘에서 루프를 사용하면 루프 내에서 여러 명령을 실행할 수 있습니다.
P.S. 여기서 괄호는 서브쉘을 실행하기 위한 연산자이며, 앞서 본 조건부 그룹화와는 다르므로 이스케이프하지 않습니다.
tr(translate)
표준 입력으로부터 오는 문자를 치환, 삭제 및 압축하여 문자열 처리를 수행합니다.
# 대소문자 변환
echo 'Ho Hoho hoho' | tr 'a-z' 'A-Z'
두 문자 집합의 크기가 다�� 경우, 뒤의 집합을 마지막 문자로 채웁니다. 예:
# 결과는 ABC XXX
echo 'abc xyz' | tr 'a-z' 'A-X'
P.S. 문자 집합 정의 형식은 시작문자-종료문자입니다. 결과가 연속된 문자 시퀀스가 아니라면 3개의 일반 문자로 간주됩니다.
주의: tr은 입력된 각 문자에 대해 매핑을 수행할 뿐, 문자열 매칭이나 치환이 아닙니다. 문자 단위의 작업이지 문자열 단위가 아닙니다.
기타 자주 사용하는 옵션:
# -d 문차 삭제
# 결과는 a, a , 579
echo 'hohoa, hoa 123, 4579' | tr -d 'ho0-4'
# -c 여집합 구하기, 보통 -d와 결합하여 여집합의 문자를 삭제하고 지정된 집합만 남김
# 결과는 hohoho1234
echo 'hohoa, hoa 123, 4579' | tr -d -c 'ho0-4'
# -s 문자 압축 (연속된 중복 문자를 하나로 변환)
# 결과는 ha, ha
echo 'hhhhhha, ha' | tr -s 'a-z'
문자 클래스(character class)를 집합으로 사용:
# 대소문자 변환
echo '124abcX1' | tr '[:lower:]' '[:upper:]'
다른 문자 클래스는 man tr을 통해 확인할 수 있습니다.
md5sum, sha1sum
이 명령들은 체크섬(checksum)을 계산하는 데 사용됩니다. 예:
# 파일의 MD5 구하기
# 결과는 `32자리 16진수 문자열 파일명`
md5sum test.sh
P.S. Mac에는 기본적으로 md5sum, sha1sum이 없으므로 별도로 설치해야 합니다.
MD5 파일로 검증:
# MD5 파일을 사용하여 파일이 올바른지 확인
md5sum -c file.md5
md5deep을 사용하여 폴더의 MD5 생성 (별도 설치 필요, sha1deep도 유사함):
# yum 설치
yum install md5deep
# 폴더의 MD5 구하기
# -r 재귀, -l 상대 경로 생성 (기본은 절대 경로)
md5deep -rl dir > dir.md5
# 모든 MD5 파일로 검증
md5sum *.md5
sort & uniq
sort 명령은 행을 정렬하고, uniq는 중복을 제거합니다. 보통 함께 사용됩니다. 예:
# file.txt 내용을 행별로 사전순 정렬하고 중복 제거
sort file.txt | uniq
# 또는
sort -u file.txt
기본적으로 사전순 오름차순 정렬이며, -n은 수치 정렬, -r은 내림차순입니다:
# 문자 숫자가 섞여 있으면 문자가 앞서게 됨
sort -n file.txt
sort -r file.txt
기타 자주 사용하는 옵션:
# 파일 내용이 정렬되어 있는지 확인, 수치 정렬 확인은 -nC
# 반환값이 0이면 정렬되어 있음을 의미
sort -C file.txt; echo $?
# 2번째 열을 기준으로 정렬
sort -k 2 file.txt
# 2번째 문자부터 5번째 문자까지 기준으로 정렬
sort -k 2,5 file.txt
# \0을 구분자로 사용 (파이프로 다른 명령과 결합할 때 유용)
sort -z file.txt
# 선행 공백 무시
sort -b file.txt
uniq 명령은 정렬된 입력에 대해서만 작동하므로 보통 sort와 함께 사용합니다:
# 유일한 행만 표시 (2번 이상 나타나는 행은 모두 필터링)
uniq -u sorted.txt
# 각 행의 출현 횟수 집계
uniq -c sorted.txt
# 중복된 행 찾기
uniq -d sorted.txt
중복 제거 시 key를 지정할 수 있습니다:
# -s 앞의 몇 문자를 건너뜀, -w는 key의 길이를 지정
uniq -s 3 -w 2 sorted.txt
P.S. Mac에는 -w 옵션이 없습니다.
split
split 명령은 큰 파일을 분할하는 데 사용됩니다. 예:
# data.txt를 1k 크기의 여러 파일로 분할
split -b 1k data.txt
기본적으로 xaa, xab, xac...와 같은 파일명이 생성됩니다. 기본적으로 크기 기준으로 엄격하게 나누므로 행이 잘리거나 한자가 깨질 수도 있습니다.
생성될 파일명을 직접 지정할 수 있습니다. 마지막 인자가 접두사이며 기본값은 x입니다. -a는 접미사 길이를 지정합니다. 기타 옵션은 man split을 확인하세요.
행 단위로 파일을 분할할 수도 있습니다:
# 각 파일당 10행씩, 파일명은 `small.aa, small.ab, small.ac...`
split -l 10 test.sh 'small.'
P.S. 이런 명령이 있는 줄 모르고 예전에 sql 백업 파일을 쪼개기 위해 큰 파일을 편집할 수 있는 텍스트 에디터를 찾아 헤매며 수동으로 분할했던 기억이 나네요...
P.S. 파일 분할을 위한 더 강력한 명령으로 csplit이 있습니다. 주로 로그 파일을 분할할 때 사용하며 지정된 텍스트 내용의 존재 여부를 조건으로 분할할 수 있습니다.
기타 팁
임시 파일 명명
Ubuntu나 Debian에는 임시 파일명(무작위 문자열)을 생성하는 tempfile 명령이 있습니다. 다른 환경에서는 RANDOM 환경 변수나 현재 프로세스 ID를 사용할 수 있습니다:
# RANDOM 환경 변수 값 가져오기
$RANDOM
# 현재 프로세스 ID 가져오기
$$
문자열 추출
%, %%, #, ## 연산자는 강력한 문자열 추출 기능을 제공합니다:
file=logo.png
# 파일명 추출
filename=${file%.*}
echo filename:$filename
# 확장자 추출
ext=${file##*.}
echo ext:$ext
사용법은 다음과 같습니다:
# var의 값에서 % 우측의 와일드카드와 매칭되는 문자열을 오른쪽에서 왼쪽 방향으로 삭제
${var%.*}
# %%는 탐욕 매칭으로 가장 긴 문자열을 찾고, %는 최단 문자열을 찾음
${var%.*}
# var의 값에서 # 우측의 와일드카드와 매칭되는 문자열을 왼쪽에서 오른쪽 방향으로 삭제
${var#*.}
# 이에 대응하는 탐욕 매칭
${var##*.}
확장자를 추출할 때는 file.txt.md5와 같이 .이 여러 개 포함된 파일명이 있을 수 있으므로 ## 탐욕 매칭을 사용하는 것이 좋습니다.
아직 댓글이 없습니다