왜 쉘이 "무용 한 고양이 사용"을 자동으로 수정하지 않습니까? [닫은]


28

많은 사람들이 줄을 따라 코드가 들어있는 원 라이너와 스크립트를 사용합니다

cat "$MYFILE" | command1 | command2 > "$OUTPUT"

첫 번째 cat기술적으로는 새로운 프로세스 (종종 시작해야하기 때문에 종종라고 "고양이의 쓸모 사용" /usr/bin/cat명령이 있었다면이 피할 수)

< "$MYFILE" command1 | command2 > "$OUTPUT"

쉘은 시작 command1하고 단순히 stdin주어진 파일을 가리 키기 만하면 되기 때문 입니다.

셸이이 변환을 자동으로 수행하지 않는 이유는 무엇입니까? "고양이의 쓸모없는 사용"구문은 읽기 쉽고 쉘은 쓸모없는 고양이를 자동으로 제거하기에 충분한 정보가 있어야한다고 생각합니다. 는 cat쉘 경로에 바이너리를 사용하는 내부 대신을 구현할 수 있어야하므로 POSIX 표준에 정의되어 있습니다. 쉘에는 정확히 하나의 인수 버전에 대한 구현과 경로의 이진 대체가 포함될 수도 있습니다.


22
어떤 경우에는 stdin이 파일이고 다른 경우에는 파이프이기 때문에 이러한 명령은 실제로 동일하지 않습니다. 따라서 엄격하게 안전한 변환은 아닙니다. 그래도 시스템을 만들 수 있습니다.
Michael Homer

14
유스 케이스를 상상할 수 없다고해서 애플리케이션이 지정된 동작을 쓸데없이 의존 할 수 없다는 의미는 아닙니다. 에서 오류 가져 오기 lseek등 여전히 동작을 정의하고 다른 결과를 야기 할 수는, 다른 차단 동작은 의미 론적으로 의미가있을 수 있습니다 당신이 무엇을 알고 있다면 변화를 만들기 위해 허용 될 다른 명령했다 그들은 상관하지 않았다 알고, 또는 그 수준에서 호환성에 신경 쓰지 않았지만 이점은 거의 없습니다. 이점이 부족하면 상황이 적합성 비용보다 더 많이 발생한다고 생각합니다.
마이클 호머

3
셸은 절대적으로 cat자체 또는 다른 유틸리티 를 구현할 수 있습니다. 또한 시스템에 속한 다른 유틸리티가 어떻게 작동하는지 알 수 있습니다 (예 : 시스템과 함께 제공된 외부 grep구현 어떻게 작동하는지 알 수 있습니다 ). 이것은 완전히 가능하기 때문에 왜 그렇지 않은지 궁금해하는 것은 전적으로 공정합니다.
마이클 호머

6
@MichaelHomer 예를 들어, 시스템과 함께 제공된 외부 grep 구현이 어떻게 동작하는지 알 수 있습니다. 그래서 이제 쉘은의 동작에 의존합니다 grep. 그리고 sed. 그리고 awk. 그리고 du. 그리고 수천 개의 다른 유틸리티가 아니라면 몇 백 명입니까?
Andrew Henle

19
나를 위해 명령을 편집하는 것은 쉘에서 좋지 않은 일입니다.
Azor Ahai

답변:


25

두 명령은 동일하지 않습니다. 오류 처리를 고려하십시오.

cat <file that doesn't exist> | less 파이프 프로그램으로 전달 될 빈 스트림을 생성합니다. 따라서 아무것도 표시하지 않는 디스플레이가 생깁니다.

< <file that doesn't exist> less 막대를 열지 못하고 열리지 않습니다.

전자를 후자로 변경하려고 시도하면 잠재적으로 공백 인 입력으로 프로그램을 실행할 것으로 예상되는 많은 스크립트가 중단 될 수 있습니다.


1
이것이 두 구문의 가장 중요한 차이점이라고 생각하기 때문에 귀하의 응답을 수락 된 것으로 표시하겠습니다. with 변형 cat은 항상 파이프 라인에서 두 번째 명령을 실행하지만 입력 리디렉션 만있는 변형은 입력 파일이없는 경우 명령을 전혀 실행하지 않습니다.
Mikko Rantalainen

그러나 <"missing-file" grep foo | echo 2실행되지는 않지만 실행 grep됩니다 echo.
Mikko Rantalainen

51

"무의미한 사용 cat"은 스크립트를 실행할 때 실제로 실행되는 것보다 코드를 작성하는 방법에 대한 것입니다. 그것은 일종의 디자인 안티 패턴 이며, 아마도 더 효율적인 방식으로 수행 될 수있는 일을하는 방법입니다. 주어진 도구를 가장 잘 결합하여 새 도구를 만드는 방법을 이해하지 못했습니다. 파이프 라인에 여러 sed및 / 또는 awk명령을 함께 묶는 것도 때로는이 동일한 안티 패턴의 증상이라고 할 수 있다고 주장합니다.

cat스크립트에서 "무용하지 않은"인스턴스를 수정 하는 것은 주로 스크립트의 소스 코드를 수동으로 수정하는 것입니다. ShellCheck 와 같은 도구는 다음과 같은 명백한 경우를 지적함으로써이를 도울 수 있습니다.

$ cat script.sh
#!/bin/sh
cat file | cat
$ shellcheck script.sh

In script.sh line 2:
cat file | cat
    ^-- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.

쉘 스크립트의 특성으로 인해 쉘이 자동으로 수행하는 것은 어려울 수 있습니다. 스크립트가 실행되는 방식은 상위 프로세스에서 상속 된 환경과 사용 가능한 외부 명령의 특정 구현에 따라 다릅니다.

쉘은 반드시 무엇인지 알 필요는 없습니다 cat. 잠재적으로의 어디에서나 어떤 명령 $PATH이나 함수 일 수 있습니다.

그것은이라면 내장 (이 일부 포탄에있을 수 있습니다),이 명령 그것의 내장의 의미를 알고하는 것처럼 파이프 라인을 재구성 할 수있는 능력이 cat명령을 사용합니다. 이를 수행하기 전에 원래 파이프 라인의 다음 명령에 대한 가정을 추가로 수행해야합니다 cat.

표준 입력에서 읽는 것은 파이프에 연결될 때와 파일에 연결될 때 약간 다르게 동작합니다. 파이프는 검색 할 수 없으므로 파이프 라인의 다음 명령이 수행하는 작업에 따라 파이프 라인이 재 배열 된 경우 다르게 동작 할 수도 있고 동작하지 않을 수도 있습니다 (입력이 검색 가능한지 여부를 감지하고 다른 경우에 다른 방식으로 수행하기로 결정할 수 있음) 어떤 경우에도 다르게 동작하지는 않습니다).

이 질문은 매우 일반적인 의미에서 " 자체적으로 구문 오류를 수정하려고하는 컴파일러가 있습니까? "(소프트웨어 엔지니어링 StackExchange 사이트)와 유사하지만, 그 질문은 구문 오류에 관한 것이지만 쓸모없는 디자인 패턴은 아닙니다. . 의도에 따라 코드를 자동으로 변경하는 아이디어는 거의 동일합니다.


쉘이 무엇인지 cat, 파이프 라인의 다른 명령 (있는 경우 규칙)을 알고 그에 따라 행동 하는 것은 완벽하게 준수합니다 . 무의미하고 너무 어렵 기 때문에 여기에 없습니다.
Michael Homer

4
@MichaelHomer 예. 그러나 동일한 이름의 함수로 표준 명령을 오버로드 할 수도 있습니다.
Kusalananda

2
@PhilipCouling 어떤 파이프 라인 명령도 신경 쓰지 않는 한 절대적으로 적합합니다. 쉘은 특히 유틸리티를 내장 또는 쉘 기능으로 대체 할 수 있으며 외부 결과를 구분할 수없는 한 실행 환경 제한이 없습니다. 귀하의 경우 와 다른 cat /dev/tty흥미로운 입니다 <.
마이클 호머

1
@MichaelHomer 외부 결과를 구분할 수없는 한 허용됩니다. 즉, 이러한 방식으로 최적화 된 전체 유틸리티 세트의 동작 은 절대 변경할 수 없습니다 . 그것은 궁극적 인 의존성 지옥이어야합니다.
Andrew Henle

3
@MichaelHomer 다른 의견에서 cat있듯이, OP의 입력이 주어지면 명령을 실행하지 않고 명령이 실제로 무엇을하는지 알 수 없다는 것은 쉘이 완벽하게 준수 하는 것 입니다. 모든 당신 (쉘) 노하우를 들어, 영업 이익은 명령이 cat"myfile을"이 단지 저장된 게임 상태, 상호 작용하는 고양이 시뮬레이션 그녀의 경로를하고, command1그리고 command2현재 재생 세션에 대한 통계를 후 처리하는 ...
alephzero

34

쓸모 없기 때문입니다.

의 경우 cat file | cmdfd 0(stdin) cmd는 파이프가되고 cmd <file일반 파일, 장치 등일 수 있습니다.

파이프에는 일반 파일과 다른 의미가 있으며 그 의미는 일반 파일의 의미 의 하위 집합 이 아닙니다 .

  • 일반 파일은 의미있는 방식 으로 select(2)편집하거나 poll(2)편집 할 수 없습니다 . select(2)거기에 항상 "준비"를 반환합니다. epoll(2)Linux 와 같은 고급 인터페이스 는 일반 파일에서 작동하지 않습니다.

  • 리눅스 시스템 호출 (가 splice(2), vmsplice(2), tee(2)) 파이프에서만 작업 [1]

cat너무 많이 사용 되기 때문에 추가 프로세스를 피할 수있는 셸 내장으로 구현 될 수 있지만 해당 경로에서 시작한 후에는 대부분의 명령을 사용하여 동일한 작업을 수행 할 수 있습니다-셸을 느리고 느린 것으로 변환 perl또는 python. 대신 연속 을 위해 파이프와 같은 구문을 사용하기 쉬운 다른 스크립팅 언어를 작성하는 것이 좋습니다. ;-)

[1] 만약 당신이 그 상황에 맞지 않는 간단한 예제를 원한다면 여기 에 주석에 대한 설명과 함께 "stdin에서 실행 바이너리"git gist 를 볼 수 있습니다 . catUUoC없이 작동하도록 내부에 구현 하면 2 ~ 3 배 더 커졌을 것입니다.


2
실제로 ksh93 cat 내부 와 같은 일부 외부 명령을 구현합니다 .
jrw32982는 Monica

3
cat /dev/urandom | cpu_bound_programread()별도의 프로세스에서 시스템 호출을 실행합니다 . 예를 들어 Linux에서는 시스템 호출에서 더 많은 난수를 생성하는 실제 CPU 작업 (풀이 비었을 때)이 수행되므로 별도의 프로세스를 사용하면 별도의 CPU 코어를 사용하여 임의의 데이터를 입력으로 생성 할 수 있습니다. 예를 들어 난수를 포함하는 1GB 텍스트 파일을 생성하는 가장 빠른 방법
Peter Cordes

4
더 중요한 것은 대부분의 경우 lseek작동하지 않음을 의미 합니다. cat foo.mp4 | mpv -작동하지만 mpv 또는 mplayer의 캐시 버퍼보다 ​​뒤로 탐색 할 수는 없습니다. 그러나 파일에서 입력을 리디렉션하면 할 수 있습니다. cat | mpv -MP4가 moov파일의 시작 부분에 원자를 가지고 있는지 확인하는 한 가지 방법 이므로 끝과 뒤로를 찾지 않고 재생할 수 있습니다 (즉, 스트리밍에 적합한 경우). 리디렉션 /dev/stdin과 함께 실행하여 검색 할 수없는 파일에 대해 프로그램을 테스트하려는 다른 경우를 쉽게 상상할 수 있습니다 cat.
Peter Cordes

이것은를 사용할 때 더욱 그렇습니다 xargs cat | somecmd. 파일 경로가 명령 버퍼 한계를 초과 하는 경우 연속 스트림이 발생하여 여러 번 xargs실행될 수 cat있지만 연속적인 스트림을 생성 할 수 있지만 원활한 결과를 얻기 위해 여러 번을 실행할 수 xargs somecmd없기 때문에 직접 사용 somecmd하지 못할 수도 있습니다.
tasket

17

쓸모없는 고양이를 감지하는 것은 정말 어렵습니다.

내가 쓴 쉘 스크립트가 있었다

cat | (somecommand <<!
...
/proc/self/fd/3
...
!) 0<&3

cat를 통해 호출 되어 쉘 스크립트 가 제거 된 경우 쉘 스크립트가 프로덕션에서 실패했습니다 su -c 'script.sh' someuser. 명백하게 불필요한 것은 cat표준 입력의 소유자가 스크립트를 실행하는 사용자에게 변경되어 스크립트를 다시 열었을 때 /proc작동했습니다.


이 경우는 cat하나의 매개 변수 가 따르는 간단한 모델을 명확하게 따르지 않으므로 쉘은 cat최적화 된 바로 가기 대신 실제 실행 파일을 사용해야 하기 때문에 매우 쉽습니다 . 그러나 실제 프로세스에 대해 다른 자격 증명이나 비표준 표준에 대한 좋은 지적.
Mikko Rantalainen

13

tl; dr : 쉘은 비용이 예상되는 이익을 초과하기 때문에 자동으로 수행하지 않습니다.

다른 답변은 stdin이 파이프와 파일 사이의 기술적 차이점을 지적했습니다. 이를 염두에두고 쉘은 다음 중 하나를 수행 할 수 있습니다.

  1. cat파일 대 파이프 구별을 유지하면서 기본 제공으로 구현 하십시오. 이것은 exec 및 아마도 포크의 비용을 절약 할 수 있습니다.
  2. 파일 / 파이프가 중요한지 확인하는 데 사용되는 다양한 명령을 알고 파이프 라인에 대한 전체 분석을 수행 한 다음 그에 따라 작동합니다.

다음으로 각 접근 방식의 비용과 이점을 고려해야합니다. 이점은 충분히 간단합니다.

  1. 두 경우에서,이 간부 (의 방지 cat)
  2. 두 번째 경우, 리디렉션 대체가 가능한 경우 포크를 피하십시오.
  3. 당신이 파이프를 사용해야 할 경우에 따라서는 수 포크 / vfork 상태를 피하기 위해 가끔 있지만, 종종합니다. cat-equivalent가 다른 파이프 라인과 동시에 실행되어야하기 때문입니다.

따라서 특히 포크를 피할 수 있으면 약간의 CPU 시간과 메모리를 절약 할 수 있습니다. 물론이 기능을 실제로 사용하는 경우에만이 시간과 메모리를 절약하십시오. 포크 / 실행 시간 만 절약 할 수 있습니다. 더 큰 파일의 경우 시간은 대부분 I / O 시간입니다 (예 : 디스크에서 파일을 읽는 고양이). 따라서 cat성능이 실제로 중요한 쉘 스크립트에서 얼마나 자주 (무의미한) 사용됩니까? 다른 일반적인 쉘 내장과 비교해보십시오 . 중요한 곳에서 사용되는 것 보다 자주 10 분의 1을 사용 test한다고 상상하기 어렵습니다 . 그것은 내가 추측하지 않은 추측입니다. 구현하기 전에 시도하고 싶은 것입니다. (또는 유사하게 다른 사람에게 기능 요청과 같은 구현을 요청합니다.)cattest

다음으로 물으십시오 : 비용은 얼마입니까? 염두에 두 가지 비용은 다음과 같습니다. (a) 셸의 추가 코드로, 크기가 커지고 (메모리 사용 가능) 유지 관리 작업이 더 필요하며 버그 등의 또 다른 지점입니다. 그리고 (b) 이전 버전과의 호환성 놀라움으로 cat인해 POSIX 는 GNU coreutils와 같은 많은 기능을 생략 cat하므로 cat내장 기능을 정확히 구현해야합니다.

  1. 추가 내장 옵션은 그리 나쁘지 않을 것입니다. 무리가 이미 존재하는 곳에 하나 더 내장되어 있습니다. 프로파일 링 데이터가 도움이된다는 것을 보여주는 경우, 좋아하는 쉘 작성자가 추가하도록 설득 할 수 있습니다.

  2. 파이프 라인을 분석 할 때 쉘이 현재 이와 같은 작업을 수행하지 않는다고 생각합니다 (일부는 파이프 라인의 끝을 인식하고 포크를 피할 수 있음). 기본적으로 쉘에 (기본) 최적화 프로그램을 추가합니다. 옵티마이 저는 종종 복잡한 코드와 많은 버그의 원인으로 판명되었습니다. 이러한 버그는 놀라 울 수 있습니다. 쉘 스크립트를 약간 변경하면 버그를 피하거나 유발할 수 있습니다.

Postscript : 쓸모없는 고양이 사용에 비슷한 분석을 적용 할 수 있습니다. 장점 : 읽기 쉬움 (command1이 파일을 인수로 사용하더라도 가능하지는 않지만) 비용 : 여분의 포크와 exec (그리고 command1이 파일을 인수로 취할 수 있다면 더 혼란스러운 오류 메시지가 나타납니다). 쓸데없이 고양이를 사용하라는 분석 결과가 나오면 계속 진행하십시오.


10

cat명령은 stdin- 의 마커로 승인 할 수 있습니다 . ( POSIX , " 파일이 '-'인 경우 cat 유틸리티는 시퀀스의 해당 지점에서 표준 입력을 읽어야합니다. ") 그렇지 않으면 파일 또는 stdin을 간단하게 처리 할 수 있습니다.

쉘 인수 $1가 다음과 같은 두 가지 간단한 대안을 고려하십시오 -.

cat "$1" | nl    # Works completely transparently
nl < "$1"        # Fails with 'bash: -: No such file or directory'

또 다른 시간 cat은 쉘 구문을 유지하기 위해 의도적으로 no-op로 사용되는 경우에 유용합니다.

file="$1"
reader=cat
[[ $file =~ \.gz$ ]] && reader=zcat
[[ $file =~ \.bz2$ ]] && reader=bzcat
"$reader" "$file"

마지막으로 UUOC가 실제로 올바르게 호출 될 수있는 유일한 시간 cat은 일반 파일 (예 : 장치 또는 명명 된 파이프가 아닌) 파일 이름과 함께 사용되며 명령에 플래그가 지정되지 않은 경우입니다.

cat file.txt

다른 상황에서는 cat그 자체의 작업이 필요할 수 있습니다.


6

cat 명령은 쉘이 반드시 수행 할 수없는 (또는 최소한 쉽게 수행 할 수없는) 작업을 수행 할 수 있습니다. 예를 들어, 탭, 캐리지 리턴 또는 줄 바꿈과 같이 보이지 않는 문자를 인쇄한다고 가정하십시오. 쉘 내장 명령만으로 그렇게 할 수있는 방법이있을 수 있지만 머리 꼭대기를 생각할 수는 없습니다. cat의 GNU 버전은 -A인수 또는 인수로 수행 할 수 있습니다 -v -E -T(그러나 다른 버전의 고양이에 대해서는 모르겠습니다). -n(GNU가 아닌 버전이이를 수행 할 수 있다면 IDK를 사용하여) 각 줄 앞에 줄 번호를 붙일 수 있습니다 .

cat의 또 다른 장점은 여러 파일을 쉽게 읽을 수 있다는 것입니다. 그렇게하려면 간단히 입력하면됩니다 cat file1 file2 file3. 쉘을 사용하여 동일한 작업을 수행하려면 신중하게 제작 된 루프가 동일한 결과를 얻을 수는 있지만 까다로울 수 있습니다. 즉, 그러한 간단한 대안이 존재할 때 그러한 루프를 작성하는 데 정말로 시간이 걸리기를 원하십니까? 나는하지 않습니다!

cat은 사전 컴파일 된 프로그램이므로 cat을 사용하여 파일을 읽으면 아마도 CPU보다 적은 CPU를 사용하게 될 것입니다 (명백한 예외는 고양이가 내장 된 모든 쉘입니다). 많은 파일 그룹을 읽을 때 이것은 분명해 보일 수 있지만 내 컴퓨터에서는 전혀 읽지 않았으므로 확신 할 수 없습니다.

cat 명령은 명령이 표준 입력을 받아들이지 않도록 강제하는 데 유용 할 수 있습니다. 다음을 고려하세요:

echo 8 | sleep

"sleep"명령은 숫자 "8"을 허용하지 않습니다. 표준 입력을 받아들이려는 의도는 없었기 때문입니다. 따라서 수면은 그 입력을 무시하고 인수 부족에 대해 불평하고 종료합니다. 그러나 다음 중 하나를 입력하면

echo 8 | sleep $(cat)

많은 포탄이 이것을로 확장 sleep 8하고 수면은 8 초 동안 기다렸다가 종료됩니다. ssh와 비슷한 것을 할 수도 있습니다.

command | ssh 1.2.3.4 'cat >> example-file'

주소가 1.2.3.4 인 시스템에 예제 파일이 추가 된이 명령은 "command"에서 출력되는 모든 것을 포함합니다.

그리고 그것은 아마도 표면을 긁는 것일 것입니다. 나는 원한다면 고양이가 유용하다는 더 많은 예를 찾을 수 있다고 확신하지만,이 게시물은 그 자체로 충분히 길다. 셸에 이러한 모든 시나리오 (및 다른 시나리오)를 모두 요청하는 것은 실제로 불가능하지 않습니다.


"쉽게 실현할 수 없습니다"
끝내겠습니다

3

사용자 는 POSIX가 아닌 catin을 가질 수 있음을 기억하십시오 (그러나 어딘가에 무언가를 기록 할 수있는 변형). 이 경우, 쉘이이를 제거하기를 원하지 않습니다.$PATHcat

PATH 변화는 동적으로 변할 수 있으며, cat 그렇게 생각하는 것이 아닙니다. 당신이 꿈꾸는 최적화를 수행하는 쉘을 작성하는 것은 상당히 어려울 것입니다.

또한 실제로 cat 는 매우 빠른 프로그램입니다. 그것을 피해야 할 실질적인 이유 (미학 제외)는 거의 없습니다.

FOSDEM2018에서 Yann Regis-Gianas 의 뛰어난 파싱 ​​POSIX 지옥 이야기를 참조하십시오 . 쉘에서 꿈꾸는 일을 시도하지 않는 다른 좋은 이유가 있습니다.

성능이 실제로 쉘의 문제라면 누군가가 정교한 전체 프로그램 컴파일러 최적화, 정적 소스 코드 분석 및 적시 컴파일 기술을 사용하는 쉘을 제안했을 것입니다 (이 세 도메인 모두 수십 년의 진보와 과학 출판물과 헌신적 인 SIGPLAN 등의 회의 ). 안타깝게도 흥미로운 연구 주제 라해도 현재 연구 기관이나 벤처 캐피탈리스트로부터 자금을 지원받지 못하기 때문에 노력할 가치가 없다고 추론하고 있습니다. 다시 말해, 쉘 최적화를위한 중요한 시장은 없을 것입니다 . 이러한 연구에 50 만 유로를 투자 할 경우 쉽게 할 수있는 사람을 쉽게 찾을 수있을 것입니다.

실제로는 성능을 향상시키기 위해 더 나은 스크립팅 언어 (Python, AWK, Guile 등)의 작은 (백 줄) 쉘 스크립트가 일반적으로 수행됩니다. 큰 셸 스크립트를 작성하는 것은 (많은 소프트웨어 공학적 이유로) 합리적이지 않습니다. 백 줄을 초과하는 셸 스크립트를 작성할 때는 좀 더 적합한 언어로 다시 작성하는 것이 좋습니다 (가독성 및 유지 관리상의 이유로). : 프로그래밍 언어 로서 쉘은 매우 열악합니다. 그러나, 많은 큰 생성 쉘 스크립트, 그리고 좋은 이유 (예 : GNU autoconf를 생성 configure스크립트).

거대한 텍스트 파일에 대해서는 단일 인수 cat로 전달하는 것이 좋지 않으며 대부분의 sysadmin은 알고 있습니다 (쉘 스크립트를 실행하는 데 1 분 이상이 걸리면 최적화를 고려하기 시작합니다). 큰 기가 바이트 파일의 경우 파일 을 처리하는 데 좋은 도구 는 아닙니다 .cat


3
"피해야 할 몇 가지 실질적인 이유"- cat some-huge-log | tail -n 5달리기를 기다린 사람 ( tail -n 5 some-huge-log끝까지 똑바로 건너 뛸 수 있지만 cat앞뒤로 만 읽는 사람)은 동의하지 않습니다.
Charles Duffy

주석은 cat수십 GB 범위의 큰 텍스트 파일 (테스트 용으로 작성된)을 확인하는 데 시간이 오래 걸립니다. 추천하지 않습니다.
Sergiy Kolodyazhnyy

1
BTW, re : "쉘 최적화를위한 중요한 시장이 없음"-ksh93 최적화 쉘이며 상당히 좋습니다. 그것은 했다 , 잠시 동안 성공적으로 상용 제품으로 판매. (슬프게도, 상업적으로 라이센스를 받으면 제대로 작성되지 않은 클론 및 기타 비용이 적지 만 비용이 적게 드는 후임자가 라이센스를 지불 할 의사가있는 사이트 외부의 세계를 점령하여 우리가 처한 상황을 초래할 수있는 틈새 시장이되었습니다. 오늘).
찰스 더피

(당신이 주목하는 특정 기술을 사용하지는 않지만 솔직히 이러한 기술 프로세스 모델에서 의미가 없습니다 . 적용되는 기술은 잘 적용되고 효과적입니다 ).
Charles Duffy

2

@Kusalananda 답변 (및 @alephzero 주석)에 추가하면 cat은 무엇이든 될 수 있습니다.

alias cat='gcc -c'
cat "$MYFILE" | command1 | command2 > "$OUTPUT"

또는

echo 'echo 1' > /usr/bin/cat
cat "$MYFILE" | command1 | command2 > "$OUTPUT"

시스템의 cat (자체) 또는 / usr / bin / cat이 실제로 연결 도구 인 이유는 없습니다.


3
동작 이외의 cat것은 POSIX에 의해 정의되므로 크게 다르지 않아야합니다.
roaima

2
@roaima : 지금 PATH=/home/Joshua/bin:$PATH cat ...무엇을하는지 알고 cat있습니까?
여호수아

1
@Joshua 정말 중요하지 않습니다. 우리 둘 다 cat재정의 할 수 있다는 것을 알고 있지만, 다른 것으로 대체해서는 안된다는 것도 알고 있습니다. 필자의 의견에 따르면 POSIX는 합리적으로 존재할 것으로 예상되는 특정 (부분 집합) 동작을 요구합니다. 때로는 표준 유틸리티의 동작을 확장하는 쉘 스크립트를 작성했습니다. 이 경우 쉘 스크립트는 추가 기능이 있다는 점을 제외하고는 대체 한 도구와 동일하게 작동하고 작동했습니다.
roaima

@Joshua는 대부분의 플랫폼에서 쉘은 알고 (또는 디렉토리가 POSIX 명령을 구현하는 실행 파일을 보유 알고). 따라서 별칭 확장 및 경로 확인이 끝날 때까지 대체를 연기 할 수 있습니다 /bin/cat. (그리고 당신은 그것을 끌 수있는 옵션으로 만들 것입니다.) 또는 cat셸을 내장 /bin/cat하여 여러 인수 에 대해 다시 사용할 수 있습니까? 와 함께 enable cat. 좋아합니다 kill. (Bash command cat가 작동 한다고 생각 했지만 내장을 건너 뛰지는 않습니다.)
Peter Cordes

별명을 제공하면 쉘은 cat해당 환경에서 더 이상 일반을 참조하지 않음을 알게됩니다 cat. 분명히, 별명을 처리 한 후에 최적화를 구현해야합니다. 항상 경로 앞에 붙는 가상 디렉터리의 명령을 나타내는 셸 내장을 고려합니다. 셸 내장 버전의 명령 (예 test:)을 피하려면 경로가있는 변형을 사용해야합니다.
Mikko Rantalainen

1

고양이에게는 두 가지 "무용지물"사용 :

sort file.txt | cat header.txt - footer.txt | less

... 여기서는 cat파일과 파이프 입력을 혼합하는 데 사용됩니다.

find . -name '*.info' -type f | sh -c 'xargs cat' | sort

... 여기서 xargs사실상 무한한 수의 파일 이름을 수락하고 cat필요한만큼 여러 번 실행 하여 하나의 스트림처럼 동작하도록 할 수 있습니다. 따라서 이것은 직접 사용 xargs sort하지 않는 큰 파일 목록에서 작동합니다 .


이 유스 케이스 둘 다 cat정확히 하나의 인수로 호출 되는 경우 쉘 내장 스텝 인 전용으로 만들어 피할 수 있습니다 . 특히 sh문자열이 전달되고 직접 xargs호출 cat되는 경우 셸이 내장 구현을 사용할 수있는 방법이 없습니다.
Mikko Rantalainen

0

다른 것들과는 별도로, cat-check cat는 실제로는 쓸모없는 IMHO에 대한 성능 오버 헤드와 혼동을 추가 할 수 있습니다. 이러한 점검은 비효율적이며 합법적 인 cat사용에 문제를 일으킬 수 있기 때문 입니다.

명령이 표준 스트림을 처리 할 때는 표준 파일 디스크립터에 대한 읽기 / 쓰기 만 신경 써야합니다. 표준 입력 인 경우 명령은 알 수 시크 / lseekable 파이프 또는 파일을 나타냅니다, 또는하지.

실제로 stdin 컨텐츠를 제공하는 프로세스를 확인하는 믹스를 추가하는 경우 파이프 반대편에서 프로세스를 찾아 적절한 최적화를 적용해야합니다. Kyle Jones 의 SuperUser 게시물 과 같이 쉘 자체와 쉘 측면에서 수행 할 수 있습니다.

(find /proc -type l | xargs ls -l | fgrep 'pipe:[20043922]') 2>/dev/null

링크 된 게시물에 표시된대로 이것은 3 개의 명령 (추가 fork()exec()s)과 재귀 순회 (따라서 많은 readdir()호출)입니다.

C와 쉘 소스 코드의 관점에서, 쉘은 이미 자식 프로세스를 알고 있으므로 재귀가 필요하지 않지만 언제 최적화하고 언제 cat실제로 쓸모가 없는지 어떻게 알 수 있습니까? 실제로 고양이 와 같은 유용한 용도가 있습니다.

# adding header and footer to file
( cmd; cat file; cmd ) | cmd
# tr command does not accept files as arguments
cat log1 log2 log3 | tr '[:upper:]' '[:lower:]'

그러한 최적화를 쉘에 추가하는 것은 아마도 낭비이며 불필요한 오버 헤드 일 것입니다. Kusalanda의 답변에서 이미 언급했듯이 UUOC는 최상의 결과를 위해 명령을 가장 잘 결합하는 방법에 대한 사용자의 이해 부족에 대한 것입니다.

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