레이블이 grep인 게시물을 표시합니다. 모든 게시물 표시
레이블이 grep인 게시물을 표시합니다. 모든 게시물 표시

k8s ingress-nginx-controller 설정(nginx.conf) 파악

# ingress-nginx(controller) 에서 ysoftman.lemon.com / 에 대한 처리가
# 어떻게 되는지 보기 위해 --v=3 옵션을 주고 ingress-nginx-controller 를
# 다시 시작(deployment 리소스가 없으면 daemonset 리소스를 수정)
# 다음과 같이 실제 nginx 설정이 어떻게 되어 있는지 볼 수 있지만 diff 만 보인다.ㅠㅠ
kubectl logs -f $(kubectl get pod -n ingress-nginx  | rg -v NAME | awk '{print$1}' | head -1) -n ingress-nginx | rg "server_name ysoftman.lemon.com" -C 50

# 실제 running 중인 ingress-nginx-controller 의 nginx.conf 을 덤프해보자.
# nginx 동작하는 노드 접속
ssh ysoftman@인그레스서버

# nginx-controller 도커 컨테이너에 접속
sudo docker exec -it --user=0 --privileged $(sudo docker ps | grep ingress-nginx-controller | awk '{print $1}') bash

# nginx 가 --with-debug 옵션으로 동작 중인지 확인
nginx -V 2>&1 | grep -- '--with-debug'

# nginx master PID 파악해서 gdb 로 열기
gdb -p $(ps -ef | grep "nginx: master" | grep -v grep | awk '{print $2}')

# (gdb) 에 아래 명령 복붙
set $cd = ngx_cycle->config_dump
set $nelts = $cd.nelts
set $elts = (ngx_conf_dump_t*)($cd.elts)
while ($nelts-- > 0)
set $name = $elts[$nelts]->name.data
printf "Dumping %s to nginx_conf.txt\n", $name
append memory nginx_conf.txt \
        $elts[$nelts]->buffer.start $elts[$nelts]->buffer.end
end

# (gdb) 종료
quit

# 덤프된 nginx_conf.txt 확인
cat nginx_conf.txt

# 호스트로 빠져 나온다.
exit

# 컨테이너 -> 호스트(노드)로 nginx_conf.txt 복사
sudo docker cp $(sudo docker ps | grep ingress-nginx-controller | awk '{print $1}'):/etc/nginx/nginx_conf.txt .

# 로컬로 빠져 나온다.
exit

# 노드 -> 로컬로 nginx_conf.txt 복사
rsync ysoftman@인그레스서버:/home/ysoftman/nginx_conf.txt .

# nginx_conf.txt 파일이 너무 크니
# ## start server ysoftman.lemon.com  ~  ## end server ysoftman.lemon.com 만 남기고 지운다.

# 문제가 있는 location 의 라인번호를 보고 다시 nginx_conf.txt 에서 찾아 보자
rg -n "location " nginx_conf.txt


#####


# 좀더 편하게 kubectl ingress-nginx 플러그인을 사용해 파악할 수도 있다.
# nginx-controller 가 daemonset 으로 동작하는 경우 pod 를 찾을 수 없다고 나온다.
# deployment 로 동작하는 경우만 작동하는것으로 보인다.
# 설치
brew install krew
kubectl krew install ingress-nginx
export PATH="${PATH}:${HOME}/.krew/bin"

# 백엔드 정보
kubectl ingress-nginx backends -n nginx-ingress

# 특정 호스트 관련 설정 정보
kubectl ingress-nginx conf -n ingress-nginx --host testaddr.local


제일빠른 ripgrep

# grep 보다 빠른 ack,sift 가 있는데 이것보다 빠른게 ripgrep(rg)다.
# 참고 https://www.peterbe.com/plog/ripgrep
# wsl(ubuntu) 기준으로 ripgrep sift asck 를 설치해 테스트 해봤다.
# 각각 2번씩 수행해서 더 빠른것을 적었다.

# grep 결과
time grep -rn yoonbyounghoon
golang/hash/hash.go:36: data = []byte("yoonbyounghoon")
grep --color=auto -rn yoonbyounghoon  0.12s user 1.38s system 84% cpu 1.776 total

# ack 결과
time ack -r yoonbyounghoon
golang/hash/hash.go
36:     data = []byte("yoonbyounghoon")
ack -r yoonbyounghoon  0.19s user 2.48s system 88% cpu 3.004 total

# sift 결과
time ../gopath/bin/sift yoonbyounghoon
golang/hash/hash.go:    data = []byte("yoonbyounghoon")
../gopath/bin/sift yoonbyounghoon  0.09s user 1.80s system 180% cpu 1.045 total

# ripgrep 결과
time rg yoonbyounghoon
golang/hash/hash.go
36:     data = []byte("yoonbyounghoon")
rg yoonbyounghoon  0.00s user 0.72s system 227% cpu 0.315 total

# 빠른 순서
ripgrep > sift > grep > ack

git command

# git 설정 확인
git config --list

# git color ui 설정
git config --global color.ui auto

# true 로 활성화하면 checkout 시에는 CRLF 로 변경되고 commit 시에는 LF 로 변경되어 커밋된다
# false 로 비활성화하면 변환없이 그대로 체크아웃, 커밋된다.
# 디폴트는 fasle 이고
# 윈도우에선 true, 맥과 리눅스에선 false 로 사용한다.
git config --global core.autocrlf  false

# git alias 를 다음과 같은 방식으로 설정 할 수 있다.
git config --global alias.br branch
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st status

# git diff 등에서의 컬러 사용
git config --global color.ui auto

# git 에디터를 vim 으로 설정(--system 은 전체 사용자, --global 은 현재 사용자)
git config --global core.editor vim

# git 머지툴을 vimdiff 로 설정
git config --global merge.tool vimdiff

# git 사용자 email 과 이름 설정
git config --global user.email "ysoftman@gmail.com"
git config --global user.name "ysoftman"

# 위 config 명령들은 실행후 .gitconfig 에 다음과 같이 alias 가 추가된다.
# .gitconfig 에 직접 추가해도 된다.
git config -e 또는 vi ~/.gitconfig
[color]
    ui = auto
[alias]
    br = branch
    co = checkout
    ci = commit
    st = status
[color]
    ui = auto
[credential]
    helper = cache
[core]
    editor = vim
[merge]
    tool = vimdiff
[user]
    email = ysoftman@gmail.com
    name = ysoftman

# 각 저장소마다 별도의 설정은 .git/config 를 수정한다.
vi .git/config
[user]
    email = ysoftman2@gmail.com
    name = ysoftman2

# 또는 글로벌 옵션 제거하고 설정
git config user.email "ysoftman@gmail.com"
git config user.name "ysoftman"

# git 2.0 이전에서는 push.default 를 설정해야 한다.
# matching : 원격 브랜치와 같은 이름이면 모두 푸시
# simple : 현재 브랜치만 푸시 (git2.0 부터 디폴트)
git config --global push.default simple

# pre-push, pre-commit 등의 hook 파일 경로(디폴트: .git/hooks) 변경
git config core.hooksPath .github

#####

# git 암호 저장
# ~/.git-credentials 파일 생성되며 id,pw 가 저장된다.
# 하지만 암호화 되지 않아 주의해야 한다.
git config --global credential.helper store

# 파일로 저장하지 않고 일정시간(디폴트 15분)동안 id,pw 를 캐싱한다.
git config --global credential.helper cache

# push 할때 현재 저장소 암호변경이 필요한경우
# credential.helper 변수를 제거해 id,pw 를 다시 입력 받도록 한다.
git config --unset credential.helper
git push

# osx 의 경우 credential 을 키체인(keychain access.app)으로도 관리한다.
# ~/.git-credential 내용이 osx의 키체인으로 등록된다.
# 현재 저장소의 키체인에 저정된 id,pw 를 확인한다.
git credential-osxkeychain get

# 수동으로 github.com 키체인 삭제(마지막에 엔터 2번입력해야 반영된다.)
git credential-osxkeychain erase
host=github.com
protocol=https

# 수동으로 github.com 키체인 등록(마지막에 엔터 2번입력해야 반영된다.)
git credential-osxkeychain store
host=github.com
protocol=https
username=ysoftman
password={깃헙 PAT(personal access token}

# 참고로 git push 되지만 다음과 같은 에러가 발생하는 경우가 있는데
# ~/.git-credentials newline 을 제거해야 한다.
warning: url has no scheme:
fatal: credential url cannot be parsed:

#####

# 새로운 git repository 생성(.git 디렉토리가 생성됨)하고 원격 저장소로 푸시
git init
git add -A
git commit -m "first commit"
git remote add origin git://github.com/ysoftman

# -u (--set-upstream)
git push -u origin master

# remote(origin) 저장소 변경
git remote set-url origin git://github.com/ysoftman

# 이미 존재하는 git repository 저장소를 로컬에 복사
# git 프로토콜 외 ssh, https 등 사용가능
# --recursive 옵션 사용시 링크된 repo 도 클론한다.
git clone git://github.com/ysoftman

# 클론 후 ysoftman1 브랜치로 체크아웃
git clone -b ysoftman1 git://github.com/ysoftman

# --single-branch 옵션까지 사용하면 해당 브랜치 커밋만 가져온다.
git clone -b ysoftman1 --single-branch git://github.com/ysoftman

# ssh 를 사용하는 경우
# 로컬에서 ssh 키 생성수 id_rsa.pub 를 github personal setting -> ssh and gpg key -> new ssh key 에 추가하고 다음과 같이 클론한다.
git clone git@github.com:ysoftman/ysoftman.git

# 파일 추가(스테이지에 올리기)
git add source_file.c

# 변경(수정,삭제) 있는 파일만 추가(tracked 파일중)
git add -u

# 전체 파일 추가(untracked 파일까지 포함)
git add -A

# 수정된 파일 자동 스테이지 추가하여 커밋
git commit -a

# 로컬 저장소에 반영(커밋)
git commit -m "commit comment."

# 마지막 커밋 내용 수정(push 이미 푸시 커밋은 수정하지 말자.)
git commit --amend

# 변경사항 없는 컷밋하기
git commit -m "no changes" --allow-empty

# a1234(git log 로 커밋 해시 확인) 커밋 되돌리기
# a1234 커밋 상태로 커밋한다.(자동 커밋되기 때문에 주의, reset 으로 커밋 취소 가능)
# a1234 revert 가 앞에 붙은 커밋 메시지를 사용한다.
git revert a1234

# 자동 커밋하지 않고 되돌리기
git revert --no-commit a1234

# 마지막 커밋 1개 되돌리기
git revert HEAD~1

# -X <option>, --strategy-option=<option>
# a1234(theirs)로 자동 커밋하지 않고 되돌리기
git revert -X theirs --no-commit a1234

# 머지 되돌리기
# 머지커밋을 보면 다음과 같이 브랜치의 시작(aaa)과 끝(ccc) 커밋이 명시되어 있다.
# Merge aaa ccc
# -m(--mainline) parent-number:머지된 브랜치의 시작 커밋aaa는 1이 된다.
git revert -m 1 머지커밋해시

# 현재 로컬 브랜치를 리모트에 푸시
git push

# pre-push hook 하지 않고 푸시하는 경우
git push --no-verify

# 현재 로컬 모든 브랜치를 리모트에 푸시
git push --all

# 로컬 저장소 develop 브랜치를 리모트 저장소 develop 로 푸시
# git push {remote_name} {local_branch}:{remote_branch}
git push origin develop:develop

# 현재 로컬 모든 tag들 리모트에 푸시
git push --tags

# 리모트 저장소 브랜치 내용을 로컬 브랜치에 반영(fetch + merge)
git pull

# Fetch all remotes (브랜치가 최신으로 업데이트되지는 않는다.)
git fetch --all
# 또는
git pull --all

# 리모트 저장소 master 를 로컬 master 로 pull 받기(최신으로 업데이트)
git pull origin master

# pull request 내용 받기(123 은 pr 번호다.)
git pull origin pull/123/head:pr-123

# 커밋 로그 보기
git log

# 커밋 로그 diff 도 보기(-p --patch 패치 생성)
git log -p

# 커밋 로그 diff 최신 10개 이전까지만 보기
# log 보기 화면에서 / 로 검색할 수 있다. 예) /my\ name\ is\ ysoftman
git log -p -10

# HEAD 에 tracked 파일들 보기
git ls-tree HEAD

# 스테이지에서 빼기
git reset

# 또는
# 새로 생긴 커맨드로 reset 보다 권장된다.
git restore --staged 파일명

# push 되지 않은 최근 커밋1개 취소
git reset HEAD~1

# 소스가 꼬였을때 서버 기준으로 강제로 업데이트 받기(이클립스 설정파일에서 자주 발생)
git reset --hard HEAD
git pull

# 원격 push된 잘못된 바로 이전 커밋(내역) 삭제하기
# 헤드로부터 1개 전까지 커밋 삭제(1개 이전 상태로 되돌린다.)
# 원격으로 강제 push
git reset --hard HEAD~1
git push -f

# 더이상 사용되지 않는 리모트 브랜치 제거하고 가져오기
git pull --prune
# 또는
git fetch --prune

# 리모트 브랜치 리스트 파악
git branch -r

# 로컬 브랜치 리스트 파악
git branch -a

# git branch -a 로 보면 remotes/origin/xxx 가 나오는데
# 리모트에서 삭제된 브랜치들을 로컬에 적용해 삭제할 수 있다.
git remote update --prune

# 브랜치 생성
git branch ysoftmanbranch1

# 존재하는 브랜치 체크아웃(에러 발생시 -f 옵션으로 강제 스위칭 가능)
git checkout ysoftmanbranch1

# 브랜치 생성하고 생성된 브랜치로 이동(체크아웃)
git checkout -b ysoftmanbranch2

# origin에서도 삭제된 브랜치로 체크아웃
git checkout 삭제된_브랜치_이름 커밋_해시값

# 생성된 브랜치 원격으로 처음으로 푸시하는 경우
git push --set-upstream origin ysoftmanbranch2

# 원격 브랜치가 있는경우 로컬에 체크아웃
# -t(track) 이 없으면 커밋이 안되고, 다른 브랜치로 체크아웃시 원격 브랜치가 로컬에서 사라진다.(git pull 로 최신 상태여야 한다.)
git checkout -t {업스트림이름}/{브랜치명}
git checkout -t origin/ysoftmanbranch3

# 태그로 체크아웃
git checkout tags/1.0.0

# 브랜치 삭제(삭제할 대상외의 브랜치로 스위칭되어 있어야 한다.)
git branch -d ysoftmanbranch1

# 브랜치 이름 변경
git branch -m ysoftman_old_branch ysoftman_new_branch

# 브랜치 이름 변경후 원격에도 반영할때
# 원격 브랜치 삭제
git push origin -d ysoftman_old_branch

# 이름 변경된 브랜치 원격 반영할때
git push origin ysoftman_new_branch

# 로컬 저장소 현재 디렉토리에서 지워진 파일 리스트 보기
git ls-files -d

# 로컬 현재 디렉토리에서 지워지거나 수정된 모든 파일 복구(참고로 svn 인경우 svn up)
git checkout ./

# 로컬 현재 디렉토리에서 지워지거나 수정된 특정 파일만 복구
git checkout -- ysoftman_file1.txt

# 로컬 특정 파일만 특정 시점으로 복구
git checkout 커밋해시값 -- ysoftman_file1.txt

# 리모트 저장소 정보 확인
git remote -v

# 리모트 저장소에 저장소 추가
git remote add new_remote_name remote_URL

# untracked 파일 삭제
# -f force, -d (directory)
git clean -fd

# 커밋전에 차이 보기(-U10, --unified=10 위아래 내용 10줄씩 보기)
git diff -U10

# ysoftmanbranch1 브랜치의 aaa.txt 파일과 차이 보기
git diff ysoftmanbranch1 -- aaa.txt

# 현재 상태
git status

# 현재 환경 상태
git show

# 커밋 내용 보기
git show 커밋해시

# 현재 변경내용 저장하고 HEAD 상태로 되돌리기
git stash save

# 변경 리스트 보기
git stash list

# 변경 내용 보기
git stash show

# 변경 내용 적용하기(stash 에 계속 유지)
git stash apply

# 변경 내용 꺼내기(stash 에서 삭제됨)
git stash pop

# a1234 b555 커밋 master 에 반영하기
git checkout master
git cherry-pick a1234 b555

# 로컬 태그 리스트
git tag

# 로컬 태그 원격 태그로 푸시
git push origin 1.1.1

# 원격 태그 리스트
git ls-remote --tags

# 로컬 태그 삭제
git tag --delete 1.1.1

# 로컬 0.0.1로 시작하는 태그 모두 삭제
git tag | grep "^0.1.1.*" | xargs git tag --delete

# 원격 태그(들) 삭제
git push --delete origin 1.1.1 1.1.2 1.1.3
# 또는 빈 태그를 푸시해도 삭제 된다.
git push origin :refs/tags/1.1.1

# 원격 태그 0.0.1로 시작하는 태그 모두 삭제
git ls-remote --tags | awk '{print $2}' | sed 's/refs\/tags\///' | grep "^0.0.1.*" | xargs git push --delete origin

# 0.0.1로 시작하는 태그들 로컬 태그삭제 후 원격태그도 삭제
delete_tags=$(git tag | grep "^0.1.1.*")
echo $delete_tags | xargs git tag --delete
echo $delete_tags | xargs git push --delete origin

# 대소문자 파일이름 변경
git mv --force ysoftman.TXT ysoftman.txt

#####

# 머지시 충돌 해결하기
# develop 을 최신으로 pull 해놓고 ysoftman123 에서 시작
git checkout develop
git pull
git checkout ysoftman123

# 방법1 - merge (커밋 히스토리 유지)
# develop -> ysoftman1 로 머지
git merge develop

# 충돌 부분 수정 수정
vim aaa.txt
# 또는
# develop <- ysoftman123 머지 상황에서 전략 옵션 사용하기
# -X <option>, --strategy-option=<option>
# 충돌부분 ysoftman123(theirs)로 덮어쓰기
git checkout develop
git merge -X theirs ysoftman123
# 또는
# 충돌부분 develop(ours)로 유지
git merge -X ours ysoftman123

# 커밋하고 푸시(커밋 메시지는 기본적으로 충돌 해결 내용으로 채워진다.)
git commit -a
git push

# 머지 취소할 경우
git merge --abort

# git pull 후 충돌발생시 머지 취소 후
# 현재 내가 변경한 사항으로 pull(머지)하기
git pull -s recursive -X ours

# 방법2 - rebase (ysoftman123 의 커밋들이 develop 이후 커밋들로 강제 변경된다.)
# ysoftman123 브랜치에서 develop 으로 rebase
git rebae develop

# 충돌 나는 부분을 확인
git status # 충돌되는 부분은 both modified 로 표시
git diff

# 충돌 부분 수정
vim aaa.txt

# 커밋(커밋 메시지는 기본적으로 충돌 해결 내용으로 채워진다.)
git commit -a

# rebase 계속해서 rebase 종료
git rebase --continue

# 강제 푸시, --force-with-lease 는 내 로컬에서 수정된게 아니면 덮어쓰지않아 --force 보다 안전하다.
git push --force-with-lease

#####

# 저장소 이전(migration)
# old 저장소 bare 로 클론 받기
git clone --bare https://github.com/ysoftman/old-repository.git

# new 저장소로 mirror 푸시
cd old-repository.git
git push --mirror https://github.com/ysoftman/new-repository.git

# old 저장소 삭제
cd ..
rm -rf old-repository.git

#####

# github wiki 이전
# old 저장소 wiki 클론 받기
git clone https://github.com/ysoftman/old-repository.wiki.git

# remote origin 을 new 저장소로 바꾸기
git remote set-url origin https://github.com/ysoftman/new-repository.wiki.git

# new 저장소 github -> wiki 생성하기
# Initial Home page 커밋이 발생하지만 강제 푸시하면 old 커밋히스토리만 남게된다.
# 참고로 -f 옵션없으면 "관계 없는 커밋 내역의 병합을 거부합니다" 에러가 발생한다.
git push -f

#####

# 패스워드 같은 민감한 데이터가 커밋,푸시돼 커밋히스토리 제거가 필요할때
# 모든 브랜치 및 태그에서 password.txt 파일 삭제 전 참고 및 주의사항
# 커밋에 password.txt 파일만 수정이 있었다면
# 커밋 히스토리 자체가 제거된다.
# 커밋에 password.txt 외 다른 파일 수정이 있었다면
# 커밋 히스토리는 있고 커멋내용에서 password.txt 파일만 제거된다.
# 로컬에 password.txt 도 삭제되니 rename 으로 백업해두자.
cp -v password.txt password.txt.bak
git filter-branch --force --prune-empty --index-filter 'git rm --cached --ignore-unmatch password.txt' --tag-name-filter cat -- --all

# 이제 강제 push 하면 원격 저장소에도 password.txt 관련 커밋 히스토리 또는 내용이 삭제된다.
git push -f

# filter-branch 삭제 후 원격 저장소에는 삭제됐지만
# 로컬 커밋 히스토리(git log --all)로 refs 모두를 보면 다음과 같이 백업이 있다.
# 참고로 git 은 ./git/refs 에 커밋해시(sha1,40자리의 hexadecimal)값 파일을 저장해 관리 한다.
refs/original/refs/remotes/origin/master 
refs/original/refs/heads/master

# 로컬 .git/refs 에 백업된 refs 삭제
git update-ref -d refs/original/refs/remotes/origin/master
git update-ref -d refs/original/refs/heads/master

#####

# rebase 로 브랜치 합치기(커밋들이 대상 브랜치(master)의 마지막 커밋 이후로 변경돼 커밋 이력이 깔끔해 진다.)
# ysoftmanbranch1 이 master 에 머지되기전
# ysoftmanbranch1 에서 master 로 rebase
# ysoftmanbranch1 브랜치가 아닌 master 로 기반으로 파생된 커밋으로 된다.
git checkout ysoftmanbranch1
git rebase master

# 만약 충돌이 발생하면, 충돌 수정후 rebase 계속
git rebase --continue

# 현재 HEAD 는 ysoftmanbranch1 커밋이다.
# master 에서 ysoftmanbranch1 을 머지하여 master 가 HEAD 가 되도록 한다.
git checkout master
git merge ysoftmanbranch1
# 만약 로컬에서 rebase 완료했는데 취소하고 싶다면 reflog 로 최근 rebase.. 바로전으로 HEAD 확인
git reflog
aaa111 HEAD@{1}: rebase: commit message
aaa222 HEAD@{2}: rebase: commit message
aaa333 HEAD@{3}: rebase: commit message
aaa444 (master) HEAD@{4}: rebase: checkout master
aaa555 (HEAD -> branch_test) HEAD@{5}: rebase: commit message
# reset 으로 rebase 전의 head 로 돌리면 된다.
git reset HEAD@{5}
# 참고로 위처럼 reflog 는 reset 외 commit 등 HEAD 변경 내용이 모두 기록된다.

#####

# fork 저장소에서 작업시
# 원본 저장소 최신 내용 fork 저장소에 반영하기
# upstream 으로 원래 저장소 추가
git remote add upstream "https://원본저장소"
git remote -v

# upstream 저장소 삭제
git remote remove upstream

# upstream 최신 내용 가져오기
git fetch upstream

# fork master 브랜치에 upstream 내용 머지
git checkout master
git merge upstream/master

# 현재 브랜치 upstream 으로 push 하기
git push -u upstream

#####

# 저장소 합치기
# 현재 저장소 서브디렉토리 aaa 생성해 https://github.com/ysoftman/simplePf 의 master브랜치 내용을 가져와 추가한다.
# 합쳐진 저장소의 커밋 히스토리까지 유지할 수 있다.
git subtree add --prefix=aaa https://github.com/ysoftman/simplePf master
git push

Windows 윈도우용 리눅스 툴 패키기

grep, awk, sed, touch 등 리눅스계열의 툴들을 윈도우에서도 사용할 수 있다.

다운로드 http://gnuwin32.sourceforge.net/br

Tip. 전체 패키지 쉽게 설치하기
GetGnuWin32 을 먼저 다운받아 압축을 푼다.
download.bat 실행하여 패키지를 다운 받고
install.bat 실행하여 패키지를 설치한다.

Linux ls find grep sed 를 이용한 유용한 명령들

# 디렉토리 내의 모든 파일들을 대상으로 문자열 찾기
# -r : 재귀수행(하위 디렉토리)
# -n : 라인번호# --include=*.txt : txt 확장자 파일만 대상
# ysoftman : 찾을 문자열
# . : 시작할 디렉토리
grep -rn --include=*.txt ysoftman .

# jpg 파일들만 검색해서 다른 디렉토리로 복사하기
# find . : 현재 디렉토리를 포함한 하위 디렉토리에서
# -name *.jpg : 확장자가 jpg 인 파일을 찾아
# -exec cp -v {}  /home/ysoftman/ \; : 찾은결과 {} 에서 /home/ysoftman 로 -v 복사상태를 표시하며 복사(-exec 는 항상 공백\; 로 끝나야한다.)
find . -name *.jpg -exec cp -v {} /home/ysoftman/ \;

# sed test1
# 하위 디렉토리(파일을 제외)만 출력하기
# ls -lR ./ ysoftman : ./ysoftman 디렉토리에서 -l : 리스트, -R : 하위 디렉토리
# | grep ":$" : 앞의 출력 결과를 파이프로 넘겨받아 : 로 끝나는 부분만 출력
# | sed 's/:/\//' : 앞의 출력 결과를 파이프로 넘겨받아 처음 부분을 [subdir] 로 바꿔서(추가) 출력
ls -lR .. | grep ":$" | sed "s/^/[subdir]/"
# sed_test.txt 내용에서 ysoftman 찾으면 출력 끝내기
cat sed_test.txt | sed "/ysoftman/q"

# sed test2
# 임시 텍스트 파일 생성
TEMP_FILE="sed_test.tmp"
echo 'aaa line1
bbb line2
ccc line3
ddd line4
eee line5
fff line6
ggg line7
hhh line8
iii line9
jjj line10' > ${TEMP_FILE}
# 라인2만 삭제하고 출력
# d 삭제
echo 'delete line 2 and print'
cat ${TEMP_FILE} | sed  "2d;"
# 2~4 라인만 출력
# -n sed 가 입력받은 각라인의 에코 출력하는것을 막는다. 조건에 해당하는것만 출력하도록 한다.
# '2,4p' 2~4라인 프린트2~4라인 프린트
echo 'print only line 2~4'
cat ${TEMP_FILE} | sed -n "2,4p"
# 3~5 7~8 라인만 출력
# ; 는 조건의 끝을 나타낸다.
echo 'print only line 3~5, 7~8'
cat ${TEMP_FILE} | sed -n "3,5p;7,8p;"
# ccc ~ ggg 패턴 사이의 내용 출력
echo 'print only pattern ccc ~ ggg '
cat ${TEMP_FILE} | sed  -n "/^ccc/,/^ggg/p;"
# ccc ~ ggg 패턴 사이의 내용만 삭제하고 출력
echo 'delete pattern ccc ~ ggg and print'
cat ${TEMP_FILE} | sed "/^ccc/,/^ggg/d;"
# 임시 텍스트  파일 삭제
rm -f ${TEMP_FILE}

# sed test3
# @뒤로 삭제
# Substitute 형식 : s/regular expression/replacement/flag
out=`(echo "ysoftman @open (12345)" | sed "s/@.*$//")`
echo "$out"___result
# 공백@ 뒤로 삭제
out=`(echo "ysoftman @open (12345)" | sed "s/ @.*$//")`
echo "$out"___result
# 컬문자의 경우
reset_color='\033[0m'
green='\033[0;32m'
# 공백이 아닌 컬러 문자가 포함되어 공백 뒤 삭제가 안된다.
echo -e "ysoftman ${green}color${reset_color} string " | sed "s/ color.*$//"
# 중간에 컬러 문자를 제거해줘야 한다.
echo -e "ysoftman ${green}color${reset_color} string " | sed "s,$(printf '\033')\\[[0-9;]*[a-zA-Z],,g" | sed "s/ color.*$//"