GNU와 BSD의 find 명령어

GNU의 find 명령어

쉘에서 find 커맨드를 통해서 어떤 경로의 파일명을 가져와야 할 상황이 생겼다. 간단하게 정의해보자면

find 명령어는 디렉터리 계층에서 파일을 검색하기 위한 명령이다.

와 같을 수 있다.

find 명령으로 검색한 결과는 하나의 라인으로 된 파일명을 출력하며 흔히 사용하는 파이프를 통해 추가적인 작업을 할 수 있다.

형식

1
2
3
4
5
find [검색할 디렉터리 경로] [옵션]

# example
find . -name "*.txt" // 현재 경로에서 .txt로 끝나는 모든 파일 출력
find ~/desktop -name "*.tet" // 사용자 홈 디렉터리/desktop 경로에서 .txt로 끝나는 모든 파일 출력

기본적으로 사용하기 위한 방법으로는 어렵지 않다. 하지만 macos를 사용중에 있어서 실행되지 않았던 옵션을 마주치게됐고 이것저것 찾아본 결과 macos의 find 명령어는 GNU의 find와는 다른 것이 원인이었다.

BSD와 GNU 이러한 것들에 대해서 많이 들어보기는 했지만 자세하게 알고 있진 못하다. 어쨌든 결과적으로는 BSD의 특징을 조금 가지고 있는 macOS와 GNU 사이에는 분명히 차이가 존재하며 이러한 이유로 find 명령어를 제대로 쓸 수 없었던 것이었다.

macOS의 find 명령어가 GNU 소프트웨어인지 확인하기 위해서 매뉴얼을 보기위한 man 명령어를 사용했다. 그 결과는

1
2
3
4
5
6
7
8
man find

# 결과
FIND(1) BSD General Commands Manual FIND(1)
...
...
...
...

와 같은 식으로 나오는 것을 확인할 수 있었다. 기존의 맥북에서 사용하는 find 명령어는 GNU가 아닌 BSD로 부터 온것임을 알 수 있다.

GNU’s find 설치

GNU의 find 를 사용하기 위해서는 따로 설치를 해줘야하며 macOS의 homebrew를 통해 할 수 있다.

1
2
brew update
brew install findutils

설치완료 후 gfind 명령어를 통해 GNU의 find를 사용할 수 있을 것이다!

1
gfind / -name "*.txt" -printf "%f\n"

GNU의 find 명령어가 아닌 BSD의 find를 사용한다면 -printf 옵션을 사용할때 에러가 난다. 사실 이부분 때문에 이와 관련된 부분을 찾아본 것이다.

Share

템플릿 태그 리터럴

tagged template literals

자바스크립트에서 HTML을 조합해 사용하는 경우가 있다. json으로 받은 데이터들을 사용하는 경우이며 underscore와 같은 패키지를 사용하곤 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const data = [
{
name: 'starbucks',
order: true,
menus: ['hand drip', 'americano']
},
{
name: 'coffeebay',
order: false,
}
];

const message = `<h1>${data[0].name}</h1>
<p>menu: ${data[0].menus}</p>`

console.log(message);

// 결과
// "<h1>starbucks</h1>
// <p>menu: hand drip,americano</p>"

data 배열 첫 번째 값의 name과 menus를 태그와 함께 출력해 보았다. 위의 예시는 간단하지만 조립해야 하는 태그와 데이터가 많아진다면 이런 방법으로 계속 할 수 있을까? 뿐만 아니라 데이터의 형식에 맞게 유동적으로 사용할 수 없다는 단점도 존재한다.

  • 일일히 하나씩 해주어야 한다.
  • 두 번째 객체 coffeebay에는 menus라는 항목이 없다.

형태에 따라 유동적으로 대응할 수도 없고 조립할 것들이 많아지면 수작업으로 하는 건 거의 불가능에 가깝다고 볼 수 있다. 또한 로직을 추가하는 것도 힘들 것이다. 조금은 더 유동적으로 사용하기 위해 함수를 작성해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const data = [
{
name: 'starbucks',
order: true,
menus: ['hand drip', 'americano']
},
{
name: 'coffeebay',
order: false,
}
];

function messageFn(tags, name, menus){
return (tags[0] + name + tags[1] + menus + tags[2])
}

const message = messageFn`<h1>${data[0].name}</h1>
<p>menu: ${data[0].menus}</p>`

console.log(message);

// 결과
// "<h1>starbucks</h1>
// <p>menu: hand drip,americano</p>"

data[1]에는 menus가 없기 때문에 data[2]에 대해서 함수를 실행하게 되면 undefined가 출력된다. 객체의 키가 없을 경우를 대비하는 로직을 추가해서 반복문을 통해 모두 출력해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
function messageFn(tags, name, menus){
if (typeof menus === "undefined"){
menus = "현재 메뉴를 준비중입니다...";
}
return (tags[0] + name + tags[1] + menus + tags[2])
}

data.forEach(function(value){
const message = messageFn`<h1>${value.name}</h1>
<p>menu: ${value.menus}</p>`

console.log(message);
})

에러 없이 잘 작동한다. 마지막으로 콘솔 출력이 아닌 HTML에 뿌려보자.

1
<div id="message"></div>
1
2
3
4
5
6
data.forEach(function(value){
const message = messageFn`<h1>${value.name}</h1>
<p>menu: ${value.menus}</p>`

document.querySelector("#message").innerHTML(message);
})

최종 코드는 아래와 같다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const data = [
{
name: 'starbucks',
order: true,
menus: ['hand drip', 'americano']
},
{
name: 'coffeebay',
order: false,
}
];

function messageFn(tags, name, menus){
if (typeof menus === "undefined"){
menus = "현재 메뉴를 준비중입니다...";
}
return (tags[0] + name + tags[1] + menus + tags[2])
}

data.forEach(function(value){
const message = messageFn`<h1>${value.name}</h1>
<p>menu: ${value.menus}</p>`

document.querySelector("#message").innterHTML += message;
});
Share

화살표 함수

화살표 표기법 함수

es6에서 새로 등장한 arrow function이다. function이라는 단어와 중괄호 갯수를 줄이려고 했으며 보이는 것 뿐만아니라 this context와 같은 내부적인 중요한 차이도 있다.

arrow function
  • function 키워드 생략가능
  • 매개변수가 하나라면 괄호 생략 가능
  • 함수 body가 식(expression) 하나라면 중괄호와 return 생략 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const f1 = function() {
return 'hello';
}
const f1 = () => 'hello';

//////////////////////

const f2 = function(nickname) {
return `Hello~! ${nickname}`;
}
const f2 = (nickname) => `Hello~! ${nickname}`;
const f2 = nickname => `Hello~! ${nickname}`;

//////////////////////

const f3 = function(a, b){
return a + b;
}
const f3 = (a, b) => a + b;
arrow function의 this

화살표 함수가 나오기 이전의 this에 대해서 먼저 살펴보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
const obj = {
register() {
setTimeout(function(){
console.log(this === window) // true
this.pprint();
}, 200)
},
pprint() {
console.log('print @-hello world-@');
}
};

obj.register(); // TypeError: this.pprint is not a function

에러가 발생했다. 그 이유는 this가 obj에 걸린 것이 아닌 window에 묶여있기 때문이다(this === window의 콘솔 결과를 보면 알 수 있다). 이 때 bind(this)를 사용하거나 화살표 함수를 통해서 obj에 lexical하게 this를 묶을 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// .bind()
const obj = {
register() {
setTimeout(function(){
this.pprint();
}.bind(this), 200)
},
pprint() {
console.log('print @-hello world-@');
}
}

obj.register(); // print @-hello world-@

// 화살표 함수
const obj = {
register() {
setTimeout(() => {
this.pprint();
}, 100)
},
pprint() {
console.log('print @-hello world-@');
}
}

obj.register(); // print @-hello world-@
Share