exit
배치 스크립트 종료할 때 exit 로 종료하면 실행한 명령창도 같이 종료된다.
goto :eof
'goto :eof' 를 사용하면 실행한 스크립트만 종료된다.
참고 : https://www.lesstif.com/software-architect/batch-17105830.html
exit
배치 스크립트 종료할 때 exit 로 종료하면 실행한 명령창도 같이 종료된다.
goto :eof
'goto :eof' 를 사용하면 실행한 스크립트만 종료된다.
참고 : https://www.lesstif.com/software-architect/batch-17105830.html
(1) 다른 프로그램이 같은 파일을 고치고 있는중일 수 있습니다.
만약 그렇다면 같은 파일을 두 개의 프로그램에서 고치지 않도록
조심하시기 바랍니다. 종료하세요. 계속하시려면 주의하세요.
(2) 이 파일을 고치다가 죽었었습니다.
만약 그렇다면 ":recover" 혹은 "vim -r a.txt"
을 사용하여 복구하십시오 (":help recovery" 참고).
이미 복구하셨었다면 스왑파일 ".a.txt.swp"
을(를) 지우셔야 이 메시지가 사라집니다.
스왑 파일 ".a.txt.swp"이 이미 존재합니다!
읽기 전용으로 열기([O]), 그냥 고치기((E)), 복구((R)), 끝내기((Q)), 버리기((A)):
오랜만에 linux 에서 작업하고 있다. ssh 접속해서 서버 로그를 vi 로 볼 일이 많다. 여러 사람이 같이 보다 보면 읽기 전용으로 열 것인지 물어보는 게 신경쓰인다.
$ vi --help
VIM - Vi IMproved 8.2 (2019 Dec 12, 빌드한 날짜 Jun 1 2020 06:42:35)
사용법: vim [인자] [파일 ..] 주어진 파일 고치기
혹은: vim [인자] - 표준입력에서 텍스트 읽기
혹은: vim [인자] -t tag 태그가 정의된 위치에서 파일 고치기
혹은: vim [인자] -q [에러파일] 첫 번째 에러가 난 파일 고치기
인자:
-- 이 뒤에는 파일 이름만
-v Vi 모드 ("vi"와 같음)
-e Ex 모드 ("ex"와 같음)
-E 향상된 Ex 모드
-s 조용한 (배치) 모드 ("ex"만)
-d Diff 모드 ("vimdiff"와 같음)
-y 쉬운 모드 ("evim"과 같음, modeless)
-R 읽기 전용 모드 ("view"와 같음)
-Z 제한된 모드 ("rvim"과 같음)
-m 수정(파일 쓰기)이 허용되지 않음
-M 텍스트 수정이 허용되지 않음
-b 이진 상태
-l 리스프 상태
-C Vi 호환: 'compatible'
-N Vi와 호환되지 않음: 'nocompatible'
-V[N][fname] Be verbose [level N] [fname에 메시지 저장]
-D 디버깅 모드
-n 스왑 파일 없이 메모리만 사용
-r 스왑 파일 목록을 표시한 뒤 끝내기
-r (파일 이름과 함께) 파손되었던 세션 복구
-L -r과 같음
-A Arabic 모드로 시작
-H Hebrew 모드로 시작
-T <terminal> 터미널 종류를 <terminal>로 설정
--not-a-term 터미널에 입출력할 수 없다는 경고하지 않음
--ttyfail 터미널에 입출력할 수 없는 경우 종료
-u <vimrc> .vimrc 대신 <vimrc>를 사용
--noplugin 플러그인 스크립트를 불러들이지 않음
-p[N] N개의 탭 열기 (기본: 파일별로 하나)
-o[N] N개의 창 열기 (기본: 파일별로 하나)
-O[N] -o와 같지만 창을 수직으로 나누기
+ 파일 마지막에서 시작
+<lnum> <lnum> 줄에서 시작
--cmd <명령> vimrc 파일을 읽기 전에 <명령>을 실행
-c <명령> 첫째 파일을 읽은 뒤 <명령>을 실행
-S <세션> 첫째 파일을 읽은 뒤 <세션> 파일 불러 들이기
-s <scriptin> <scriptin> 파일에서 Normal 상태 명령 읽기
-w <scriptout> 모든 입력된 명령을 <scriptout> 파일에 추가
-W <scriptout> 모든 입력된 명령을 <scriptout> 파일에 저장
-x 암호화된 파일 고치기
--startuptime <file> startup timing 메시지를 <file>에 저장
-i <viminfo> .viminfo 대신 <viminfo>를 사용
--clean 'nocompatible', Vim defaults, no plugins, no viminfo
-h 혹은 --help 도움말(이 메시지)을 출력한 뒤 끝내기
--version 판 정보를 출력한 뒤 끝내기
$ vi -R <filename>
-R 옵션을 사용해서 읽기 전용 모드로 실행하면 위 메시지를 보지 않을 수 있다.
> xcopy /y src\a.txt dst\a.txt
dst\a.txt은(는) 대상의 파일 이름입니까
아니면 디렉토리 이름입니까?
(F = 파일, D = 디렉터리)
xcopy 로 파일 복사 배치를 만들다 보면 파일인지 디렉토리인지 물어보는 입력문이 나와서 난감하다.
XCOPY 원본 [대상] [/A | /M] [/D[:날짜]] [/P] [/S [/E]] [/V] [/W]
[/C] [/I] [/Q] [/F] [/L] [/G] [/H] [/R] [/T] [/U]
[/K] [/N] [/O] [/X] [/Y] [/-Y] [/Z] [/B] [/J]
[/EXCLUDE:file1[+file2][+file3]...] [/COMPRESS]
source 복사할 파일을 지정합니다.
대상 새 파일의 디렉터리 및/또는 파일 이름을 지정합니다.
/A 보관 특성을 가진 파일만 복사하며
보관 특성을 수정하지 않습니다.
/M 보관 특성을 가진 원본 파일만 복사하며
보관 특성을 지웁니다.
/D:m-d-y 지정된 날짜 이후에 바뀐 파일을 복사합니다.
날짜가 지정되지 않으면 대상 파일보다 새로운
원본 파일만 복사합니다.
/EXCLUDE:file1[+file2][+file3]...
문자열을 포함하는 파일 목록을 지정합니다.
각 문자열은 파일의 다른 행에 있어야 합니다.
일부 문자열이 복사할 파일의 절대 경로의 일부분과
일치하면 복사할 파일에서 제외됩니다.
예를 들어 \obj\ 또는 .obj와 같은 문자열을 지정하면
obj 디렉터리 내의 모든 파일을 제외하거나
.obj 확장자를 갖는 모든 파일을 제외합니다.
/P 각 대상 파일을 만들기 전에 물어봅니다.
/S 비어 있지 않은 디렉터리와 하위 디렉터리를 복사합니다.
/E 비어 있는 경우를 포함하여 디렉터리와 하위 디렉터리를 복사합니다.
/S /E 스위치와 같으며 /T를 수정하는 데 사용될 수 있습니다.
/V 새 파일의 크기를 검증합니다.
/W 복사하기 전에 아무 키나 누릅니다.
/C 오류가 생겨도 복사를 계속합니다.
/I 대상을 찾을 수 없고 두 파일 이상을 복사하면
대상을 디렉터리로 지정합니다.
/Q 복사하는 동안 파일 이름을 표시하지 않습니다.
/F 복사하는 동안 원본과 대상 파일의 전체 경로를 표시합니다.
/L 복사할 파일을 표시합니다.
/G 호화 기능을 지원하지 않은 대상에 암호화된 파일을
복사하도록 허용합니다.
/H 숨겨진 파일과 시스템 파일도 복사합니다.
/R 읽기 전용 파일을 겹쳐 씁니다.
/T 파일은 복사하지 않고 디렉터리 구조만 복사합니다. 빈 디렉터리와
하위 디렉터리는 포함되지 않습니다. /T /E 스위치를 함께 사용하면
빈 디렉터리와 하위 디렉터리가 포함됩니다.
/U 대상에 이미 있는 파일을 업데이트합니다.
/K 특성을 복사합니다. 일반적인 Xcopy는 읽기 전용 특성을 다시 설정합니다.
/N 만들어진 짧은 파일 이름을 사용하여 복사합니다.
/O 파일 소유권과 ACL 정보를 복사합니다.
/X 파일 감사 설정을 복사합니다(/O 의미).
/Y 기존 대상 파일을 덮어쓸지 여부를
묻지 않습니다.
/-Y 기존 대상 파일을 덮어쓸지 여부를
묻습니다.
/Z 다시 시작할 수 있는 모드에서 네트워크 파일을 복사합니다.
/B 바로 가기 링크와 링크 대상을 복사합니다.
/J 버퍼를 사용하지 않은 I/O로 복사합니다. 매우 큰 파일에 권장합니다.
/COMPRESS 해당되는 경우 파일 전송 중에 네트워크 압축을
요청합니다.
스위치가 COPYCMD 환경 변수에 미리 설정되어 있을 수 있습니다.
명령줄에 있는 /-Y와 함께 무시될 수 있습니다.
/Y 로 덮어쓰기 여부 제어가 가능하고 /I 를 사용할 경우 대상을 디렉터리로 지정 가능하지만 대상을 파일로 지정은 불가능하다.
> echo f | xcopy /y src\a.txt dst\a.txt
dst\a.txt은(는) 대상의 파일 이름입니까
아니면 디렉터리 이름입니까?
(F = 파일, D = 디렉터리) f
src\a.txt
1개 파일이 복사되었습니다.
이럴 경우 파이프를 이용해서 f 값을 넘겨줘서 처리하면 된다.
출처 : https://superuser.com/questions/34303/xcopy-not-surpressing-file-directory-query
svn 같은 서버형 형상 관리 툴은 로그 보기를 하면 서버 기준으로 보이는데 git 은 로컬 기준이 기본이다.
> git log origin
remote origin 에 누가 무슨 작업을 해놨는지 확인하려면 콘솔에서 git log origin 을 치면 된다.
> git fetch
> git log FETCH_HEAD
아니면 fetch 만 받아서 FETCH_HEAD 로그를 보는 방법도 있다.
출처 : https://stackoverflow.com/questions/16315379/log-of-remote-history
> gitk --remotes
기본 ui tool 인 gitk 를 주로 사용하는데 gitk 는 rev-list 파람을 따라간다. --remotes 옵션을 사용하면 remote 에 있는 모든 branch 가 보인다. --remotes[=<pattern>] 형식으로 필터링할 수 있다는데 잘 모르겠다.
> git fetch
> gitk FETCH_HEAD
그래서 gitk 를 사용할 때도 fetch 받은 후에 FETCH_HEAD 를 파람으로 추가해서 확인하고 있다.
참고 : https://git-scm.com/docs/gitk/
/d/test/work/gits/pp (master)
$ git branch -l
dev
* master
릴리즈용 브랜치 이름이 branch/release/20220226(0_1) 이런 식으로 리모트 브랜치 이름 그대로 로컬 브랜치 이름 만들었다가 마음에 안드는 경우가 있다.
/d/test/work/gits/pp (master)
$ git branch -m master main
/d/test/work/gits/pp (main)
$
git branch -m <old name> <new name> 을 이용해서 브랜치 이름을 변경할 수 있다.
참고 : https://git-scm.com/docs/git-branch
(2022-03-05) P.S. remote 브랜치와 이름이 다르면 push 할 때 살짝 번거로울 수 있다.
Unity Editor 를 사용하다 보면 에디터만 켰는데도 수정되거나 추가된 파일들이 있는 경우가 있다. 서버 작업자 입장에서는 귀찮지만 업데이트 전에 날려버리는게 좋다.
$ git checkout -- .
checkout 명령어를 이용하면 수정된 파일들은 되돌릴 수 있다. 하지만 Untracked 파일들은 남아 있다.
$ git clean -f
Removing PpProgram/test.cpp
$ git status
Untracked files:
(use "git add <file>..." to include in what will be committed)
PpProgram/cleantest/
git clean -f 명령어를 사용하면 Untracked 파일들을 삭제할 수 있다.
$ git clean -fd
Removing PpProgram/cleantest/
$ git status
nothing to commit, working tree clean
git clean -fd 를 사용하면 Untracked 디렉토리까지 삭제할 수 있다.
출처 : https://blog.outsider.ne.kr/1164
Visual Studio 로 빌드할 때 출력 창에 빌드 시간이 안보여서 핸드폰 스탑워치로 측정했었다. 검색해보니 옵션 > 빌드 및 실행 > MSBuild 프로젝트 빌드 출력의 세부 정보 표시를 '보통' 이상으로 설정하면 아래와 같이 경과 시간이 표시된다.
lockfree 로 multiple producer single consumer queue 를 구현한 코드(https://github.com/mstump/queues/blob/master/include/mpsc-queue.hpp)를 분석하고 있는데 move semantic 도 안쓴 옛날 스타일 같았다.
최신 코드를 찾아봤는데 딱히 업데이트는 없었고 std::aligned_storage 를 사용했는데 placement new/delete 가 없어서 문제될 것 같다는 코멘트가 있었다.
mpsc_queue_t() :
_head(reinterpret_cast<buffer_node_t*>(new buffer_node_aligned_t)),
_tail(_head.load(std::memory_order_relaxed))
{
buffer_node_t* front = _head.load(std::memory_order_relaxed);
front->next.store(NULL, std::memory_order_relaxed);
}
~mpsc_queue_t()
{
T output;
while (this->dequeue(output)) {}
buffer_node_t* front = _head.load(std::memory_order_relaxed);
delete front;
}
void
enqueue(
const T& input)
{
buffer_node_t* node = reinterpret_cast<buffer_node_t*>(new buffer_node_aligned_t);
node->data = input;
node->next.store(NULL, std::memory_order_relaxed);
buffer_node_t* prev_head = _head.exchange(node, std::memory_order_acq_rel);
prev_head->next.store(node, std::memory_order_release);
}
bool
dequeue(
T& output)
{
buffer_node_t* tail = _tail.load(std::memory_order_relaxed);
buffer_node_t* next = tail->next.load(std::memory_order_acquire);
if (next == NULL) {
return false;
}
output = next->data;
_tail.store(next, std::memory_order_release);
delete tail;
return true;
}
private:
struct buffer_node_t
{
T data;
std::atomic<buffer_node_t*> next;
};
typedef typename std::aligned_storage<sizeof(buffer_node_t), std::alignment_of<buffer_node_t>::value>::type buffer_node_aligned_t;
buffer_node_t 의 std::aligned_storage 를 new 로 생성 후 reinterpret_cast 한 다음에 바로 사용하고 있는데 위험해 보이는 코드다.
https://en.cppreference.com/w/cpp/types/aligned_storage
cppreference 의 Note 를 보면 aligned_storage 로 생성한 초기화 안된 공간을 placement new 를 통해 object 를 생성하고 명시적으로 destructor 를 호출한다고 되어 있다.
visual studio 의 std::aligned_storage 구현 코드를 보면 단순히 double 보다 큰 char [] 공간만 잡힌다.
template <class _Ty, size_t _Len>
union _Align_type { // union with size _Len bytes and alignment of _Ty
_Ty _Val;
char _Pad[_Len];
};
template <size_t _Len, size_t _Align, class _Ty>
struct _Aligned<_Len, _Align, _Ty, true> {
using type = _Align_type<_Ty, _Len>;
};
template <size_t _Len, size_t _Align>
struct _Aligned<_Len, _Align, double, false> {
using type = _Align_type<max_align_t, _Len>;
};
...
template <size_t _Len, size_t _Align = alignof(max_align_t)>
struct aligned_storage { // define type with size _Len and alignment _Align
using _Next = char;
static constexpr bool _Fits = _Align <= alignof(_Next);
using type = typename _Aligned<_Len, _Align, _Next, _Fits>::type;
};
new 한 공간을 reinterpret_cast 해서 사용하는게 아니라 placement new 호출 후 사용하는 게 안전하다.
mpsc_queue_t() {
buffer_node_aligned_t* al_st = new buffer_node_aligned_t;
buffer_node_t* node = new (al_st) buffer_node_t();
_head.store(node);
_tail.store(node);
node->next.store(nullptr, std::memory_order_relaxed);
}
~mpsc_queue_t() {
T output;
while (this->dequeue(&output)) {
}
buffer_node_t* front = _head.load(std::memory_order_relaxed);
front->~buffer_node_t();
::operator delete(front);
}
참고 : https://hackage.haskell.org/package/direct-rocksdb-0.0.1/src/rocksdb-5.8/util/mpsc.h
constructor/destructor 가 있는 class 들을 union 으로 사용할 일이 없어서 몰랐는데 member 간 전환할 때 명시적으로 destructor 와 placement new 를 호출해주자.
#include <iostream>
#include <string>
#include <vector>
union S
{
std::string str;
std::vector<int> vec;
~S() {} // needs to know which member is active, only possible in union-like class
}; // the whole union occupies max(sizeof(string), sizeof(vector<int>))
int main()
{
S s = {"Hello, world"};
// at this point, reading from s.vec is undefined behavior
std::cout << "s.str = " << s.str << '\n';
s.str.~basic_string();
new (&s.vec) std::vector<int>;
// now, s.vec is the active member of the union
s.vec.push_back(10);
std::cout << s.vec.size() << '\n';
s.vec.~vector();
}
위 예제를 보면 std::string, std::vector<int> 형식의 member 를 가진 union type S 가 있다. S.str 사용 후 vec member 를 사용하려고 할 때 destructor (~basic_string()) 와 placement new(new (&s.vec) std::vector<int>) 를 명시적으로 호출해주는 것을 볼 수 있다. 위와 같이 명시적으로 호출해주지 않으면 해당 객체의 virtual table 이 이상해져서 access violation exception 이 발생할 수 있다.
참고 : https://en.cppreference.com/w/cpp/language/union
업데이트되더니 UI 언어가 한국어로 바뀌어서 적응이 안된다. 설정에도 언어 바꾸는 건 없던데 난감했다. 검색해보니 설정 파일(%LOCALAPPDATA%\plastic4\client.conf) 을 수동으로 수정해줘야했다. 언어 설정을 찾아서 en 으로 바꾸고 다시 실행하면 UI 언어가 바뀌었다.
출처 : https://stackoverflow.com/questions/57779175/how-to-change-the-language-of-plastic-scm