`watch`가`ls / tmp`를 $ HOME의 내용으로 나열하는 이유는 무엇입니까?


13

/tmp/디렉토리 에있는 파일 수를 보려고합니다 . 이를 위해이 명령이 작동한다고 생각했습니다.

watch sh -c 'ls /tmp/|wc -l'

그러나 ls인수가없는 것처럼 작동 합니다. 즉,에 ~있으며 대신 대신 많은 파일을 얻습니다 /tmp/. 해결 방법을 찾았습니다.

watch sh -c 'ls\ /tmp/|wc -l'

그런데 왜 내가 사이의 공간을 탈출해야하나요 ls과를 /tmp/? 출력이 공급 watch되도록 명령이 어떻게 변환 되지만 인수로 전달되지 않습니까?lswc/tmp/ls


1
watch "sh -c 'ls /tmp | wc -l'"이 명령을 수행하면 원하는 효과를 얻을 수 있습니다. 이것은 잘못을 보지 않고 시도해 sh -c ls /tmp보면 홈 디렉토리를 얻을 수 있습니다 (그러나 이유는 모르겠습니다 ...)
Jacob Minshall

8
아니 대답하지만 당신은 사용하고 watch당신이 통과 것을 잘못 국지적 인 명령을 watch차례로에 의해 공급 watchsh -c당신이하고 효과가있어, 그래서 sh -c두 번.
iruvar

궁금한 점이 있으면 소스를 살펴볼 수도 있습니다 .
michas

1
@JacobMinshall의 이유는 간단하다 다음은 /tmp에 인수 인 sh에, 그 경우가 아닌 인수 ls.
Charles Duffy

답변:


17

차이점은 다음을 통해 볼 수 있습니다 strace.

$ strace -ff -o bq watch sh -c 'ls\ /tmp/|wc -l'
^C
$ strace -ff -o nobq watch sh -c 'ls /tmp/|wc -l'
^C
$ grep exec bq* | grep sh
bq.29218:execve("/usr/bin/watch", ["watch", "sh", "-c", "ls\\ /tmp/|wc -l"], [/* 54 vars */]) = 0
bq.29219:execve("/bin/sh", ["sh", "-c", "sh -c ls\\ /tmp/|wc -l"], [/* 56 vars */]) = 0
bq.29220:execve("/bin/sh", ["sh", "-c", "ls /tmp/"], [/* 56 vars */]) = 0
$ grep exec nobq* | grep sh
nobq.29227:execve("/usr/bin/watch", ["watch", "sh", "-c", "ls /tmp/|wc -l"], [/* 54 vars */]) = 0
nobq.29228:execve("/bin/sh", ["sh", "-c", "sh -c ls /tmp/|wc -l"], [/* 56 vars */]) = 0
nobq.29229:execve("/bin/sh", ["sh", "-c", "ls", "/tmp/"], [/* 56 vars */]) = 0

역 따옴표의 경우 ls /tmp 받는 하나의 인자로 전달 -csh예상대로 실행됩니다. 이 인용 부호가 없으면, 명령은 대신에 split을 제공 watch하며 ,이 명령은 sh제공된을 차례로 실행 sh하므로 ls인수 로만 전달되므로 -c하위 서브 sh는 베어 ls명령 만 실행 하고 현재 작업 내용을 나열합니다. 예배 규칙서.

그래서 왜 합병증 sh -c ...? 단순히 달리지 watch 'ls /tmp|wc -l'않겠습니까?


오, 실제로 strace그것을 시도하지 않았다 .
Ruslan

1
실제로`는 백 따옴표 (또는 백틱)입니다. 이 질문은 백 슬래시 인 \에 관한 것입니다.
G-Man, 'Reinstate

@Ruslan : 나는이 댓글이 게시 이 답변에을 은 주석이므로 이 답변에가 . thrig는 " backquote case, ls /tmpis is ..." 라고 말하고 " 이 backquote 없이는 command is ..."라고 말하며 명령 에서 백 슬래시 를 참조 할 때 bqnobq파일 이름으로 사용 합니다 . ls\ /tmp
G-Man, 'Reinstate

8

두 가지 주요 범주가 있습니다 watch명령의 (명령을 정기적으로 실행하는 명령 watch은 표준 명령이 아니며, watchFreeBSD의 다른 tty 행에서 스누핑과는 완전히 다른 시스템도 있습니다 ).

하나는 공백이있는 인수의 연결을 쉘에 이미 전달하고 (실제로는 call sh -c <concatenation-of-arguments>) 쉘을 호출하지 않고 지정된 인수로 지정된 명령을 실행하는 것입니다.

첫 번째 상황에 있으므로 다음과 같이하면됩니다.

watch 'ls /tmp/|wc -l'

할 때 :

watch sh -c 'ls /tmp/|wc -l'

당신의 watch실제로 실행 :

sh -c 'sh -c ls /tmp/|wc -l'

그리고 인라인 스크립트를 sh -c ls /tmp/실행 중 입니다.ls$0/tmp/ (그래서 ls인수 및 목록 현재 디렉토리없이 실행됩니다).

watch첫 번째 범주 의 일부 구현 (Linux의 procps-ng 의 구현) 은 두 번째 범주 -x와 같은 동작을 수행 하는 옵션을 허용합니다 watch. 따라서 거기에서 할 수있는 일 :

watch -x sh -c 'ls /tmp/|wc -l'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.