한 파일을 다른 파일로 리디렉션하는 것이 UUOC (cat의 쓸모없는 사용)입니까?


36

내용을 내용과 file2일치 시키려면 file1분명히 실행할 수 있습니다 cp file1 file2.

내가 보존하려는 경우, 모든file2 을 제외 등의 내용 소유자, 권한, 확장 속성, ACL을, 하드 링크, 등, 그때 실행 싶지 않을 것이다 cp. * 난 그냥를 풍덩하려는 경우 의 내용 file1file2.

다음과 같이 보입니다.

< file1 > file2

그러나 작동하지 않습니다. file2아무것도 잘리지 않고 쓰여지지 않습니다. 하나,

cat < file1 > file2

작동 합니다.

첫 번째 버전이 작동하지 않는다는 사실에 놀랐습니다.

두 번째 버전은 UUOC입니까? 단순히 리디렉션을 사용하여 명령을 호출하지 않고이 작업을 수행 할 수 있습니까?

참고 : UUOC는 진정한 안티 패턴보다 실용적인 지점이라는 것을 알고 있습니다.

* 으로 tniles09 발견 , cp 이 경우에는 사실 일이다.


3
여부는 < file1 > file2당신이 원하는 것은 쉘 의존한다.
Michael Homer

13
음, 그것은 이다 의 쓸모없는 사용 <...
jwodder

2
무슨 안티 패턴은 ?
mikeserv

6
@jwodder-사실이 아닙니다. 특히 사본에 대해 이야기 할 때. 때 발생하는 고려 file1존재하지 않거나 다른 읽을 당신은 그것을 열기 < 전에 > 출력이 열리고, 다음 허용 할 때 무슨 생각 cat을 열려고 할 수 있습니다.
mikeserv

3
@JonathanLeffler zsh에서 리디렉션이있는 빈 명령 cat은 기본적으로 두 번째 명령을 실행하여 기본적으로 호출 됩니다. 주석에 맞는 것보다 자세한 내용은 아래의 Stéphane Chazelas의 답변을 참조하십시오 .
Michael Homer

답변:


58

cat < file1 > file2UUOC가 아닙니다. 클래식, <그리고 >할 리디렉션 시스템 레벨에서 파일 기술자 중복에있는 해당합니다. 스스로 파일 기술자 중복은 (잘, 일하지 않는 >리디렉션과 함께 열을 O_TRUNC너무 정확, 출력 리디렉션 출력 파일을 잘라야 할). < >기호가 혼동 하지 않도록하십시오. 리디렉션은 데이터를 이동하지 않으며 파일 디스크립터를 다른 파일 디스크립터에 지정합니다.

이 경우 file1해당 파일 디스크립터를 열고 파일 디스크립터 0( <file1== 0<file1)에 file2지정하고 해당 파일 디스크립터를 파일 디스크립터 1( >file2== 1>file2)에 지정하십시오.

이제 두 개의 파일 디스크립터가 생겼으므로 두 파일 사이에 데이터를 셔블하는 프로세스가 필요합니다 cat.


11
어쩌면 나일지도 모르지만이 답변에서 내가 가장 좋아하는 부분은 "삽"이라는 단어를 사용하는 것입니다. :) 매우 분명합니다. 감사합니다.
와일드 카드

1
@Wildcard 나는 "삽"보다 "펌프"를 선호했지만 여전히 좋은 단어입니다. +1
Mehrdad

왜 삽이 좋은 단어입니까?
bubakazouba

1
하나는 데이터가 버퍼에 의해 버퍼로 복사 될 때 한 더미에서 다른 더미로 한 번에 가득 찬 먼지 더미를 삽으로 삽니다. 좋은 비유입니다.
bsd

1
첫 번째 문장에서 파일 디스크립터가 복제되고 있다고 말합니다. 그것들이 복제되거나 재 지정되고 있습니까 (두 번째 단락과 기능의 동작이 나타내는 것처럼)?
Greg Bell

17

다른 사람들이 지적했듯이 문제의 행동은 셸에 따라 다릅니다. 당신 (OP)이 지적했듯이, 이것은 약간의 유쾌 하고 어쩌면 유머합니까? , 일종의 주제.

그러나 GNU 시스템에서는 초기 전제에 다른 솔루션이 있습니다 cp --no-preserve=all file1 file2. 이것을 시도해보십시오. 설명 된 상황을 만족시킬 것이라고 생각합니다 (예 : file2속성을 수정하지 않고 내용 수정).

:

$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 16 Dec 16 12:21 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Lookout, world!
    Hello, world!
$ cp --no-preserve=all fred fezzik 
$ ls -l
    total 8
    -rw-r--r-- 1 tniles sambashare 14 Dec 16 12:22 fezzik
    -rw-r--r-- 1 tniles tniles     14 Dec 16 12:16 fred
$ cat *
    Hello, world!
    Hello, world!

업데이트 실제로, 내 시스템 cp자체는 -a또는 -p지정 되지 않은 한 속성을 유지하는 것으로 나타났습니다 . bash 쉘과 GNU coreutils를 사용하고 있습니다. 매일 새로운 것을 배우는 것 같아요 ...


하드 링크 및 다른 권한을 포함한 테스트 결과 (와일드 카드 기준) :

$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 file2
913965 -rwxrw---- 2 pete    vagrant 39 Dec 16 20:35 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the original contents of file2
$ cp file1 file2
$ ls -li
total 12
913966 -rw-rw-r-- 1 vagrant vagrant 30 Dec 16 20:26 file1
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 file2
913965 -rwxrw---- 2 pete    vagrant 30 Dec 16 20:37 hardlinktofile2
$ cat file1
This is the contents of file1
$ cat file2
This is the contents of file1
$ 

좋은. 하드 링크 및 다른 권한을 포함하여 자체 테스트를 실행했으며 올바른 것으로 보입니다.
와일드 카드

내 테스트 결과를 추가했습니다. 당신이 상관하지 않기를 바랍니다. :) ACL이나 확장 된 속성을 테스트하지는 않았지만 inode 번호 가 유지 된다는 점을 감안하면 99 %라고 확신합니다.
와일드 카드

좋아 ... 전혀 신경 쓰지 마 :-)
tniles

13

에서 zsh쉘, < file1 > file2작품, 쉘이 호출 않습니다 cat.

단지 재 지정없이 명령이나 과제, 구성 명령 행의 경우 zsh를 원용 $NULLCMD( cat만 리디렉션하지 않는 한 기본적으로)을 인 <경우에 한 $READNULLCMD( pager대신 호출 기본 설정). (이것은 에뮬레이션 zshsh아니거나 csh에뮬레이션 이 아닌 경우 에뮬레이션하는 쉘처럼 동작합니다).

그래서:

< file1 > file2

실제로는

cat < file1 > file2

< file1

와 같다

pager < file1

공식적으로,이 구문은 경우 ksh93 작동하지 않습니다
fpmurphy

8
< from > to

거기에 명령이 없기 때문에 작동하지 않습니다. 프로세스가 없습니다. 쉘은 파일을 열고 생성하고 경로 재 지정을 정렬합니다 (이 파일을 참조하는 파일 디스크립터가 0 및 1 : 표준 입력 및 표준 출력으로 구성됨). 그러나 표준 입력에서 읽고 표준 출력에 쓰기 위해 루프를 실행할 필요는 없습니다.

zsh이 "널 (null) 명령"경우 사용자가 구성 할 수있는 명령을 대체하여이 작업을 수행합니다. 명령은 명령 행에 표시되지 않지만 여전히 있습니다. 프로세스가 작성되며 동일한 방식으로 작동합니다. NULLCMD입니다 cat그래서, 기본적으로 < from > to실제로 의미 cat < from > to 에서 zsh하지 않는 한, NULLCMD다른 것으로 설정되어; "암시 적 고양이"명령입니다.

"cats의 쓸모없는 사용" cat은 파일에서 파일을 읽고 다른 프로세스에 데이터를 공급하기 위해 중개자로 사용될 때 발생합니다. 이 프로세스의 파일 설명자는 원래 파일에 연결될 수 있습니다.

경우 cat상황에서 제거하고, 나머지 명령은 여전히 같은 작업을 수행 할 수 있도록, 그것은 쓸모가 없다. 제거 할 수 없으면 쓸모가 없습니다.

# useless, removable:
$ cat archive.tar | tar tf -    #  -->  tar tf archive.tar

# not removable (in POSIX shell):
$ cat > file
abc
[Ctrl-D]

# likewise:
STRING=$(cat file)

cat입니다 대체 가능은 같은 것이 아니다. 예를 들어 파일을 만드는 대신 cat > file사용할 수 있습니다 vi file. cat동일한 작업을 수행하기 위해 남은 것을 사용하는 동안 은 제거로 계산되지 않습니다 .

경우 cat는 IS 에만 물론 제거 할 수 없습니다의 다음 파이프 라인의 명령; 남은 것을 재배치하지 않으면 동등한 작업을 수행합니다.

일부 쉘 스크립터 cat는 입력 피연산자를 명령 행의 왼쪽 가까이로 이동할 수 있다고 생각 하기 때문에 사용합니다. 그러나 리디렉션은 명령 줄의 어느 곳에 나있을 수 있습니다.

# If you're so inclined:
# move source archive operand to the left without cat:
$ < archive.tar tar xf - > listing

btw, f -tar 를 사용할 필요는 없습니다 . tar xf -그냥 tar x입니다.
dnt

@mikeserv cat파일 생성과 관련이있는 곳은 어디 입니까? 대답은 껍질이 이것을한다고 분명히 말합니다. 무슨 문제가 > file있습니까? 나는 종종 기존 파일을 길이가 0으로 자르거나 그러한 파일이 존재하는지 확인하기 위해 단독으로 사용합니다. 이 질문은 왜 < from > to처럼 작동하지 않는지 cat < from > to, UUoC와 관련하여 "왜 cat좋은 대안이 아닌지 이유를 알려주세요 cp." 가 아닙니다 .
Kaz

1
@dnt tar테이프 아카이버 입니다. tar기본적으로 많은 구현이 여전히 첫 번째 테이프 장치에서 작동합니다.
Stéphane Chazelas

1

< file1 > file2 쉘에 의존적이며 zsh에서는 bash가 작동하지 않습니다.

편집 : 삭제 된 허위 진술


cp -a의 특성 보존 FILE1을 하고 덮어 파일 2의 속성을. 원하는 행동의 반대. 게다가 나는 하드 링크로 어떤 일이 일어날 지 매뉴얼 페이지를 보더라도 알 수 없지만 file2 의 하드 링크는 보존 되지 않는다고 말하는 것이 안전하다고 생각합니다 .
와일드 카드

네 말이 맞아, 나는 그 질문을 충분히 읽지 않았다.
tastytea

1

모든 좋은 답변 외에도 다음을 시뮬레이션 하여 UUOC를 피할 수 있습니다 cat.

awk 1 file1 > file2   # For line-oriented text, not binaries.
dd if=file1 of=file2  # Works for binary files, too.
# many more geeky ways.

이 명령들은 평범한 것처럼 파일 메타 데이터를 복사하지 않습니다 cp.


그러나 이점이 없으며 장점 (성능, 신뢰성) 만 있다는 점은 언급 할 가치가 cat있습니다. 여기서 두 파일 설명자 사이에 데이터를 입력하는 명령이 필요하며 cat그 중 가장 좋은 것 중 하나입니다. Linux에서 fifo pv를 위해 사용할 수있는 것도 참조하십시오 splice()( fadvise(POSIX_FADV_SEQUENTIAL)GNU 와는 달리 cat).
Stéphane Chazelas

dd바이너리 파일에 대한 명령은 좋은 것 같습니다 ... 또는 것입니다 cat바이너리 파일뿐만 아니라 그냥 작동?
와일드 카드

@Wildcard cat는 바이너리 파일에서도 작동합니다 (Unix는 일반적으로 구별하지 않습니다. 그러나 일부 도구는 awk, grep, wc 등의 라인 단위로 작동합니다 ... POSIX는 또한 가장 큰 최소 라인 길이를 정의하므로 이론상 줄 중심 도구는 지나치게 큰 줄을 다루기를 거부 할 수 있습니다.)
Jens

2
@ StéphaneChazelas이 답변은 또한 혀-뺨입니다. 시즌에도 불구하고 일부 사람들은 재미에 알레르기가있는 것 같습니다 (귀하가 아닌 쉘 전문 지식과 Opengroup 표준이 중요합니다).
Jens

sed '' < file1 > file2;-)
Digital Trauma

0

작동하면 해결하지 마십시오.

나는 사용할 것이다

cat < file1 > file2

의미론의 PC를 땀을 흘리지 마십시오.

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