처음부터 읽기 위해 두 번째 파일 설명자를 사용하지 않고 Mac의 bash에서 파일 설명자를 되감는 방법은 무엇입니까?

처음부터 읽기 위해 두 번째 파일 설명자를 사용하지 않고 Mac의 bash에서 파일 설명자를 되감는 방법은 무엇입니까?

환경:GNU bash, 버전 3.2.57(1)-릴리스(x86_64-apple-darwin20)

0을 시도하십시오:

exec 3<> "$(mktemp)"    # open file descriptor 3 to a temp file for read/write
echo 'foo' >&3          # write 'foo' to descriptor 3
read bar <&3            # read contents of descriptor 3 to variable named bar (not using -u 3)
echo $?                 # exit status returns "1"
exec 3>&-               # close file descriptor 3

위의 코드 조각에서는 $bar로 설정할 것으로 예상했지만 "foo"파일 설명자 3의 위치가 파일 설명자 파일의 끝에 있기 때문에 작동하지 않습니다.

1번을 시도해보세요:

exec 3<> "$(mktemp)"    # open file descriptor 3 to a temp file for read/write
echo 'foo' >&3          # write 'foo' to descriptor 3
cat <&3                 # echo contents of of descriptor 3 to STDOUT
echo $?                 # exit status returns "0"
exec 3>&-               # close file descriptor 3

설명자 3의 파일 위치가 끝에 있기 때문에 이 역시 실패합니다.

C/C++에서는 다음을 수행할 수 있습니다.되감기(...) 및 fseek(...)생성된 파일 임시 파일의 파일 포인터를 mktemp파일의 시작 부분으로 재설정합니다.

알려진 해결 방법은 다음에서 제공됩니다.여기:(두 번째 설명자 사용)

myTempFile="$(mktemp)"  # create temp file and assign to $myTempFile
exec 3> "$myTempFile"   # open file descriptor 3 for writing to $myTempFile
exec 4< "$myTempFile"   # open file descriptor 4 for reading of $myTempFile
echo 'foo' >&3          # write 'foo' to descriptor 3
read bar <&4            # read contents of descriptor 4 to variable named bar
echo $?                 # exit status returns "0"
echo "$bar"             # echo "foo"
exec 3>&-               # close file descriptor 3
exec 4>&-               # close file descriptor 4

질문™(최종):

처음부터 읽기 위해 두 번째 파일 설명자를 사용하지 않고 bash에서 파일 설명자를 되감는 방법은 무엇입니까?

참고: 설치하고 싶지 않습니다.크쉬 93되감기 기능을 사용하세요.

exec 3<> "$(mktemp)"
echo 'foo' >&3
# Magic Happens here
read bar <&3             # expect $bar == "foo"
echo $?                  # expect "0"
exec 3>&- 

답변1

이것은 흥미로운 문제이지만(30년 동안 셸에서 수행한 적이 없는 문제입니다). 잘못된 도구를 사용하려고 했을 수도 있습니다.

유닉스(UNIX, BSD, MacOS, Gnu/Linux)에는 파이프가 있습니다. 파이프는 두 개의 파일 설명자가 있는 특수 파일(보조 저장소/디스크가 아님)입니다. 하나는 쓰기용이고 하나는 읽기용입니다. 읽기 설명자는 항상 쓰기 설명자 뒤에 옵니다. 데이터는 읽은 후 삭제됩니다.

echo a_command | another_command

명령을 실행할 때 파이프를 생성할 수 없는 경우가 있습니다. 이러한 경우 명명된 파이프나 Unix 소켓을 사용할 수 있습니다.

UNIX 소켓은 프로세스 중 하나에 의해 생성되고 삭제됩니다. 이것도 두 가지 방법입니다.

명명된 파이프는 두 프로세스와 독립적으로 생성될 수 있습니다.

답변2

zshksh93시스템 호출을 위한 내장 래퍼가 있지만 bash 는 없으므로 이를 lseek()수행하려면 별도의 유틸리티를 호출해야 합니다.lseek()파일 설명 열기fd에 첨부되어 있습니다. zshmacOS에는 기본적으로 설치되어 있으므로가지다를 사용하려면 bash래핑된 내장 sysseek함수를 정의하면 됩니다.zshsysseek

sysseek() {
  zsh -c '
    zmodload zsh/system
    sysseek "$@" || syserror -p "$0: "
  ' sysseek "$@"
}

그리고 다음을 사용하세요:

sysseek -u 3 0

fd 3을 처음으로 되감습니다.

시스템이 없는 경우 또 다른 옵션은 보다 널리 사용 가능한 기능을 zsh사용하는 것입니다 .perl

sysseek() { # args: fd, mode, offset
  perl -e '
    my ($fd, $mode, $offset) = @ARGV;
    open FD, ">&", $fd or die "fd $fd: $!\n";
    seek FD, $mode, $offset or die "seek: $!\n";
  ' -- "$@"
}

그리고 다음을 사용하세요:

sysseek 3 0 0

fd 3을 처음으로 되감습니다.

두 번째 매개변수는 다음과 같습니다.

  1. 시작 위치를 기준으로 찾습니다( sysseek -w start기본값 zsh).
  2. zsh현재 위치( 's ) 를 기준으로 sysseek -w current찾기
  3. 파일 끝( zsh's )을 기준으로 sysseek -w end검색합니다 .

답변3

쓰기 설명자와 읽기 설명자 생성을 분리합니다.

exec 3>file
echo foo >&3
exec 3<file
cat <&3
exec 3<&-

설명자 3개의 테이블이 덮어쓰기되어 읽기 전용이 됩니다. 일반 설명자를 사용하는 것은 의미가 없습니다.

변수에서 설명자 번호를 숨깁니다.

{ echo foo >&$fd; exec {fd}<&-; } {fd}<>file
{ cat <&$fd; } {fd}<>file
exec {fd}<&-

리디렉션이 먼저 수행되므로 $fd변수는 블록 내부에 작성되고 값을 갖습니다. 핸들은 ksh93에서처럼 자동으로 닫히지 않으며 블록 끝에서 또는 다음 명령을 사용하여 명시적으로 닫아야 합니다(두 가지 옵션 표시). 다음 bash 버전에 내장 변수 도입을 대비하여 자동 닫기 동작으로 변경될 수 있습니다. 이 호출 형식을 사용하면 명령이 필요하지 않습니다.exec {fd}<&-

관련 정보