프로그램이 cook
하나의 매개변수, 즉 요리할 음식의 레시피가 포함된 텍스트 파일의 경로명을 취한다고 가정해 보겠습니다. 스크립트에서 프로그램을 호출 bash
하고 문자열 변수에 레시피를 포함했다고 가정해 보겠습니다.
#!/bin/bash
the_recipe="$(cat << EOF
wash cucumbers
wash knife
slice cucumbers
EOF
)"
cook ... # What should I do here? It expects a file, but I only have a string.
파일 이름 인수가 필요한 경우 명령에 레시피를 어떻게 전달합니까?
파일을 전달하기 위해 임시 파일을 만드는 것을 고려했지만 이에 대해 다른 방법이 있는지 궁금합니다.
답변1
/dev/stdin
표준 입력을 나타내는 "가짜" 파일 이름을 사용할 수 있습니다.
따라서 다음을 실행하십시오.
echo "$the_recipe" | cook /dev/stdin
echo 명령과 파이프는 지정된 변수의 내용을 다음 명령의 표준 입력으로 보냅니다 cook
. 그런 다음 표준 입력(별도의 파일 설명자)을 열고 읽습니다.
답변2
셸의 프로세스 교체 기능을 사용하는 또 다른 방법은 bash
운영 체제에 따라 명명된 파일 설명자( ) 아래 또는 아래에 FIFO를 생성하는 것입니다. 대체 구문()은 FIFO 또는 FD의 이름으로 대체되며 그 안에 있는 명령은 백그라운드에서 실행됩니다./tmp
/var/tmp
/dev/fd/*
<(cmd)
cook <(printf '%s\n' "${the_recipe}")
이제 명령은 cook
변수의 내용을 마치 파일에 있는 것처럼 읽습니다.
이는 여러 입력 파일에서도 작동합니다.
cook <(printf '%s\n' "${the_1st_recipe}") <(printf '%s\n' "${the_2nd_recipe}")
답변3
이는 응용 프로그램의 기능에 따라 다릅니다. 명명된 파일의 사용을 주장할 수도 있고 주장하지 않을 수도 있으며, 찾을 수 있는 파일의 사용을 주장할 수도 있고 주장하지 않을 수도 있습니다.
익명 파이프
일부 응용 프로그램은 어디에서나 입력을 읽습니다. 일반적으로 기본적으로 표준 입력에서 읽습니다. 문자열 형식의 데이터가 있고 이를 애플리케이션의 표준 입력에 전달하려는 경우 여러 가지 방법이 있습니다. 파이프를 통해 정보를 전달할 수 있습니다.
printf '%s' "$the_recipe" | cook # passes $the_recipe exactly
printf '%s\n' "$the_recipe" | cook # passes $the_recipe plus a final newline
echo
쉘에 따라 백슬래시가 깨질 수 있으므로 여기서는 사용 하지 마십시오 .
응용프로그램이 파일 매개변수 사용을 요구하는 경우 -
표준 입력을 허용할 수 있습니다. 이는 일반적인 관례이지만 체계적이지는 않습니다.
printf '%s\n' "$the_recipe" | cook -
애플리케이션에 실제 파일 이름이 필요한 경우 이를 전달하여 /dev/stdin
표준 입력을 나타냅니다.
printf '%s\n' "$the_recipe" | cook /dev/stdin
일부 응용 프로그램의 경우 이것만으로는 충분하지 않습니다. 특정 확장자를 갖는 것과 같은 특정 속성을 가진 파일 이름이 필요하거나 임시 파일이 생성되는 쓰기 가능한 디렉터리에 파일 이름이 필요합니다. 이 경우 일반적으로 임시 파일이 필요하지만 때로는 명명된 파이프로 충분할 때도 있습니다.
명명된 파이프
파이프 이름을 지정할 수 있습니다. 완전성을 위해 이것을 언급하지만 가장 편리한 방법은 거의 없습니다. 디스크의 데이터를 가져오는 것을 방지합니다. 응용 프로그램에 이름이 제한된 파일이 필요하지만 파일을 찾을 수는 필요하지 않은 경우에 적합합니다.
mkfifo named.pipe
printf '%s\n' "$the_recipe" >named.pipe & writer=$!
cook named.pipe
rm named.pipe
wait "$writer"
(오류 확인은 생략했습니다.)
임시 파일
신청서에탐색 가능한파일을 사용하려면 임시 파일을 만들어야 합니다. 검색 가능한 파일은 응용 프로그램이 한 번에 일부를 읽으면서 이동할 수 있는 파일입니다. 파이프는 이것을 허용하지 않습니다. 뒤로가 아니라 처음부터 끝까지 순차적으로 읽어야 합니다.
Bash, ksh 및 zsh에는 임시 파일을 통해 문자열을 입력으로 전달하는 편리한 구문이 있습니다. (이미 있는 경우에도) 항상 문자열에 개행 문자를 추가합니다.
cook <<<"$the_recipe"
다른 셸을 사용하거나 임시 파일이 포함된 디렉터리를 제어하려면 임시 파일을 수동으로 만들어야 합니다. 대부분의 유니스는 다음을 제공합니다.mktemp
유용임시 파일을 안전하게 생성하세요. (이런 식은 절대 사용하지 마세요 ! 다른 사용자로 실행 중인 다른 프로그램도 파일을 하이재킹할 수 있습니다.) 이는 임시 파일을 생성하고 중단되면 삭제를 처리하는 스크립트입니다.… >/tmp/temp.$$
tmp=
trap 'rm -f "$tmp"' EXIT
trap 'rm -f "$tmp"; trap "" HUP; kill -INT $$' HUP
trap 'rm -f "$tmp"; trap "" INT; kill -INT $$' INT
trap 'rm -f "$tmp"; trap "" TERM; kill -INT $$' TERM
tmp=$(mktemp)
printf '%s\n' "$the_recipe" >"$tmp"
cook "$tmp"
임시 파일이 생성되는 위치를 선택하려면 TMPDIR
이라는 환경 변수를 설정하세요 mktemp
. 예를 들어 임시 파일의 기본 위치 대신 현재 디렉터리에 임시 파일을 생성하려면 다음을 수행합니다.
tmp=$(TMPDIR="$PWD" mktemp)
( $PWD
대신 을 사용하면 .
절대 파일 이름이 제공되므로 동일한 파일을 다시 지정할 cd
걱정 없이 안전하게 스크립트를 호출할 수 있습니다.)$tmp
응용 프로그램에 특정 확장자를 가진 파일 이름이 필요한 경우 임시 디렉터리를 만들고 그 안에 파일을 만들어야 합니다. 임시 디렉터리를 생성하려면 를 사용하세요 mktemp -d
. TMPDIR
임시 디렉터리가 생성되는 위치를 제어하려면 환경 변수를 다시 설정하세요.
tmp=
trap 'rm -rf "$tmp"' EXIT
trap 'rm -rf "$tmp"; trap "" HUP; kill -INT $$' HUP
trap 'rm -rf "$tmp"; trap "" INT; kill -INT $$' INT
trap 'rm -rf "$tmp"; trap "" TERM; kill -INT $$' TERM
tmp=$(mktemp -d)
printf '%s\n' "$the_recipe" >"$tmp/myfile.ext"
cook "$tmp/myfile.ext"
답변4
더 복잡한 솔루션을 시도하기 전에 해당 버전이 매개변수 (대시)를 파일 이름으로 cook
지원하는지 확인하십시오 . -
이 규칙이 지원되면 cook
다음과 같이 표준 입력에서 읽도록 지시합니다.
echo "$the_recipe" | cook -
또는
cook - <<<"$the_recipe"