Bash는 표준 출력을 파일로 리디렉션하는 데 자주 실패합니다(cat에서).

Bash는 표준 출력을 파일로 리디렉션하는 데 자주 실패합니다(cat에서).

나는 보통 다음을 사용하여 텍스트 파일에 추가합니다 cat.

cat >> FILE

실수로 파일을 덮어쓰는 것을 방지하기 위해 별칭을 사용합니다(단일 파일 사용 >).

alias a='cat >>'

Enter는 줄을 변경하고, Ctrl+는 D명령을 종료합니다. 저는 홈 폴더에 여러 개의 텍스트 파일을 작성합니다. 이 파일은 모두 제가 만들고 소유하고 편집할 수 있습니다.

내 데스크탑 Linux 시스템(Fedora 39) 및 Termux(Android)에서 입력을 정상적으로 받아들이는 것처럼 보이지만 명령이 파일로의 리디렉션을 중지한 경우가 몇 번 있었습니다. 수백 줄이 누락되었습니다. 주로 제가 붙여넣은 URL이 누락되었습니다. 명령이 한동안 실행된 후에만 발생하는 것 같습니다.

cat >>리디렉션이 작동을 멈출 수 있는 이유가 있나요 ? 예를 들어, 입력에 특수 문자가 있으면 차이가 있나요?

고쳐 쓰다: 개별 파일의 inode 번호가 계속 변경되는 것을 확인했습니다( $ ls -li또는 정확한 시간을 확인하는 데 사용 $ stat -c '%w'). 이런 일이 발생합니다.Syncthing은 동기화 파일을 다시 생성하도록 설계되었기 때문에. 앞으로 이 소프트웨어를 어떻게 사용하는지 재평가해야 할 것입니다. 처음에 동기화에 대해 언급하지 않아서 죄송합니다.

내가 자동화한 명령에서 적어도 sed -i(파일을 제자리에서 편집하여) inode도 교체했습니다.

명령 cat >> FILE도 교체해야 합니다(제공된 조언, 설명 및 답변 참조).

답변1

를 실행한 후 cat >> file쉘은 fd 1의 하위 프로세스에 있는 현재 작업 디렉토리에서 열리고 file성공하면 해당 프로세스에서 실행됩니다.O_WRONLY|O_CREAT|O_APPENDcat

그렇지 않은 경우 쉘은 오류 메시지를 인쇄하고 실행되지 않습니다 cat.

cat또한 명령을 찾을 수 없는 경우 오류 메시지를 인쇄합니다.

cat그러면 루프에서 fd 0을 읽고 읽은 내용을 fd 1에 씁니다.

마찬가지로 실패하면 오류 메시지가 인쇄됩니다.

실행 중인 프로세스가 cat신호에 의해 종료되거나 중단되면 쉘은 이를 stderr에도 보고해야 합니다(예:파일 크기 제한을 초과했습니다.SIGXFSZ사용하거나 죽이는 경우일시 중지(tty 입력)SIGTTIN을 통해 일시중지된 경우).

fd 0이 tty 장치에서 열려 있고 해당 tty 장치가 동일한 경우 쉘은 일반적으로 실행하기 전에 명령을 읽습니다. cat쉘은 자체 라인을 입력하기 전과 동일한 방식으로 tty를 구성합니다. 편집기.줄 규칙.

icanon일반적으로 이는 선 규칙이 대략적인 선 편집기를 구현하는 모드 에 있음을 의미합니다 .

그 중에서 줄 편집기는 실제로 특수 문자를 인식하는 유일한 도구입니다. stty -a목록이 제공됩니다. 나는:

$ stty -a
speed 38400 baud; rows 43; columns 159; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc

icanon위에서 언급한 내용을 볼 수 있습니다 . ^C, ^\, ^?, ^U, ^D, , ^Q, , ^S, , , , ^Z, ^R, ^W, 문자는 특수 처리됩니다. //대상(내 경우에는 활성화됨), /대상(위)은 Linux에서 지원되지 않습니다.^V^O^C^Z^\isig^S^Qixondiscard^O

예 를 들어 foobar^Ubaz다음을 입력 하면foobar사망, 그러나 다시 입력하면 에코에서 해당 내용이 제거되는 것을 볼 수 있습니다.

입력 ^C문자는 cat도중에 종료됩니다 read.

하지만요즘 대부분의 터미널 에뮬레이터는 붙여넣을 때 이러한 문자를 제거합니다.. 따라서 붙여넣을 때 이런 일이 발생하려면 여전히 스트리핑 작업을 수행하지 않는 터미널을 사용하거나 kill/ werase/ intr... 설정 중 일부를 비제어 문자로 설정해야 합니다. 이는 병리적입니다. .

줄 편집기에는 편집할 수 있는 줄의 크기에도 제한이 있습니다. Linux에서는 IIRC의 경우 4095바이트입니다. 따라서 이 값보다 큰 줄을 붙여 넣으면 4095번째 바이트를 초과하는 내용은 모두 삭제됩니다.

icanon모드에서는 tty 라인 편집기가 종료될 때 가 반환되며 , 이는 cat또는 또는 any 또는 문자를 입력(on으로 변환)할 때 발생합니다.read()^M^Jicrnl^Jeoleol2eof

그러나 어쨌든 cat정상적으로 종료되면, 즉 ^CSIGINT on 또는 SIGQUIT on에 의해 종료 되지 않거나 ^\SIGTSTP on에 의해 일시 중단되지 않고 ^Z오류가 보고되지 않으면 터미널에서 입력을 읽고 문서에 기록합니다. .

요약하자면, 당신이 시도하는 일은 정상적인 상황에서는 발생해서는 안 되며, 제가 생각할 수 있는 유일한 경우는 병리적인 경우입니다.

  • 보고된 tty 설정이 stty -a모두 버그가 있었습니다.
  • 또는 붙여넣은 데이터에 tty 드라이버의 줄 편집기에서 해석되는 제어 문자가 포함되어 있으며 어떤 이유로 터미널 편집기에서 해당 문자를 제거하지 않습니다.

cat셸에서 보고된 오류를 확인하지 못하거나 생각했던 것과 다른 디렉터리에 파일을 생성하거나 cat런타임에 삭제, 교체, 이름 바꾸기 또는 자르기 등의 인간 오류를 무시하지 마십시오(예:사물을 동기화귀하의 의견에 using)을 언급하셨습니다.

해당 별칭을 사용하여 대신 을 a='cat >>'입력하면 stdin과 동일 하며 stdin에서 읽고 대신 stdin에 출력을 씁니다 .a some filea 'some file'cat >> some filecat file >> somecatfilesomesome file

이 별칭에 대한 가능한 개선 사항(GNU 가정 tee)은 다음과 같습니다.

a() {
  rlwrap -pblue -S 'add> ' tee --output-error=warn -a -- "$@" > /dev/null
}

원래 tty 드라이버( 셸로 사용하는 경우 이미 익숙함) rlwrap보다 고급 라인 편집기를 제공 하고 일부 입력을 기다리고 있음을 더 명확하게 알려주는 프롬프트가 있습니다.bash

그리고 를 사용하면 tee한 번에 여러 파일에 입력을 쓸 수 있습니다.

답변2

실수로 파일을 덮어쓰는 것을 방지하는 것이 목표라면 적절한 쉘 변수 설정을 고려하십시오. 예를 들어 bash,

set -o noclobber    # Do not allow > to overwrite a file
set -C              # The same

set -o noclobber
echo >ddd
echo >ddd
-bash: ddd: cannot overwrite existing file

set +o noclobber
echo >ddd

관련 정보