bash에서 stdout 또는 파일을 에코하는 우아한 솔루션

bash에서 stdout 또는 파일을 에코하는 우아한 솔루션

일부 결과를 생성하는 bash 애플리케이션이 있고 stdout사용자가 선택한 파일에 결과를 에코하고 싶습니다. 다른 대화형 메시지도 화면에 표시하기 때문에 >결과를 파일에 표시하려고 할 때 사용자에게 명시적으로 리디렉션을 사용하도록 요구하는 것은 옵션(*)이 아닙니다. 해당 메시지도 파일에 표시되기 때문입니다.

이제 해결책이 생겼지만 보기 흉합니다.

if [ -z $outfile ]
then
    echo "$outbuf"    # Write output buffer to the screen (stdout)
else
    echo "$outbuf" > $outfile  # Write output buffer to file
fi

나는 , to 및 다른 것과 $outfile동일한 변수를 가지려고 노력했지만 실제로 stdout에 쓰는 대신 해당 이름을 가진 파일에만 씁니다. 더 우아한 솔루션이 있습니까?stdout&1

(*) 이런 목적으로 속여서 사용할 수도 있지만 stderr그것도 추악할 것 같죠?

답변1

먼저, 당신은echo임의의 데이터 출력 방지.

Linux 기반 시스템 이외의 시스템에서는 다음을 사용할 수 있습니다.

logfile=/dev/stdout

Linux의 경우 이는 일부 유형의 stdout에서 작동하지만 stdout이 소켓인 경우 실패합니다. 또는 stdout이 일반 파일인 경우 stdout이 현재 작성된 파일 위치에 있는 대신 파일이 잘립니다.

그렇지 않으면 Bourne과 같은 쉘에서는 방법이 없습니다가정 어구리디렉션(다음을 사용할 수 있음 eval)

eval 'printf "%s\n" "$buf" '${logfile:+'> "$logfile"'}

바꾸다바꾸다, 전용을 사용할 수 있습니다파일 설명자:

exec 3>&1
[ -z "$logfile" ] || exec 3> "$logfile"

 printf '%s\n' "$buf" >&3

이것의 한 가지 (사소한) 단점은 kshfd 3 를 제외하고 스크립트에서 실행되는 모든 명령으로 누출된다는 것입니다. 를 사용하면 대신 작업을 수행 zsh할 수 있지만 이에 상응하는 작업은 없습니다.sysopen -wu 3 -o cloexec -- "$logfile" || exitexec 3> "$logfile"bash

또 다른 일반적인 관용구는 다음과 같은 함수를 사용하는 것입니다.

log() {
  if [ -n "$logfile" ]; then
    printf '%s\n' "$@" >> "$logfile"
  else
    printf '%s\n' "$@"
  fi
}

log "$buf"

답변2

  1. 설정.outfile"/dev/stdout"
  2. 사용자가 파일 이름을 선택하거나 덮어쓰거나 outfile기본값을 그대로 두도록 합니다.
  3. printf '%s\n' "$outbuf" >"$outfile"

내가 사용하는 printf이유는 "왜 printf가 echo보다 나은가요?".

이 솔루션에 대한 참고 사항은 다음을 참조하세요.Stefan Chazeras의 답변.

답변3

이 시도

#!/bin/bash
TOSCREEN="1" # empty OR 0 to log to file
if [[ ! -z "$TOSCREEN" && $TOSCREEN == "1" ]]; then
    echo "$outbuf"    # Write output buffer to the screen (stdout)
else
    if [[ ! -f $outfile ]]; then
      #echo -e "Making file "
      touch "$outfile"
    fi  
    echo "$outbuf" >> $outfile  # Write output buffer to file
fi

답변4

#!/bin/bash -ue

function stdout_or_file()
{
    DUMP_FILE=${1:-}

    if [ -z "${DUMP_FILE}" ]; then
        # print stdin to stdout
        cat
    else
        # dump stdin to a file
        sed -n "w ${DUMP_FILE}"
    fi
}

echo "foo" | stdout_or_file "${outfile}"

이는 ${1:-}bash에만 해당되며 "-u" 모드에서 특히 유용합니다. 다른 쉘에서도 작동하는 일반적인 단일 라이너는 다음과 같습니다.

echo "foo" | if [ -z "${outfile}" ]; then cat; else sed -n "w ${outfile}"; fi

관련 정보