쉘 스크립트에서 임시 파일을 만드는 방법은 무엇입니까?

쉘 스크립트에서 임시 파일을 만드는 방법은 무엇입니까?

/tmp스크립트를 실행할 때 디렉터리에 임시 파일을 만들고 싶습니다 .

스크립트를 실행한 후 스크립트가 스크립트를 지웁니다.

쉘 스크립트에서 이를 어떻게 수행합니까?

답변1

tmpfile=$(mktemp /tmp/abc-script.XXXXXX)
: ...
rm "$tmpfile"

파일 설명자를 열고 삭제하면 스크립트가 종료될 때(종료 및 충돌 포함) 파일이 삭제되도록 할 수 있습니다. /proc/$PID/fd/$FD파일 설명자가 열려 있는 한 파일은 계속 사용 가능합니다(스크립트의 경우, 실제로 다른 프로세스의 경우는 아니지만 해결 방법). 파일이 닫히면(프로세스가 종료될 때 커널이 자동으로 이 작업을 수행함) 파일 시스템이 파일을 삭제합니다.

# create temporary file
tmpfile=$(mktemp /tmp/abc-script.XXXXXX)

# create file descriptor 3 for writing to a temporary file so that
# echo ... >&3 writes to that file
exec 3>"$tmpfile"

# create file descriptor 4 for reading from the same file so that
# the file seek positions for reading and writing can be different
exec 4<"$tmpfile"

# delete temp file; the directory entry is deleted at once; the reference counter
# of the inode is decremented only after the file descriptor has been closed.
# The file content blocks are deallocated (this is the real deletion) when the
# reference counter drops to zero.
rm "$tmpfile"

# your script continues
: ...

# example of writing to file descriptor
echo foo >&3

# your script continues
: ...

# reading from that file descriptor
head -n 1 <&4

# close the file descriptor (done automatically when script exits)
# see section 2.7.6 of the POSIX definition of the Shell Command Language
exec 3>&-

답변2

mktemp임시 파일을 만드는 데 사용됩니다 . 이 유틸리티는 생성된 파일의 전체 경로를 반환합니다.

temp_file=$(mktemp)

또는 임시 생성목차:

temp_dir=$(mktemp -d)

스크립트가 끝나면 임시 파일이나 디렉터리를 삭제할 수 있습니다.

rm "${temp_file}"
rm -r "${temp_dir}"

참고: 인수로 지정된 디렉터리에 mktemp파일을 생성합니다 . 추가 옵션과 동작을 수정하는 방법은 유틸리티 설명서를 참조하세요./tmp--tmpdir

답변3

일부 쉘에는 내장 기능이 있습니다.

다루기 힘든

zsh임시 파일을 사용하여 프로세스를 교체하는 형태입니다 =(...). 예를 들어 =(echo test)를 포함하도록 확장합니다 test\n.

$ {cat $file; ls -l /dev/fd/3; echo test2 >&3; cat $file} 3<> ${file::==(echo test)}
test
lrwx------ 1 stephane stephane 64 Jan 30 11:19 /dev/fd/3 -> /tmp/zshMLbER0
test2

명령이 완료되면 파일이 자동으로 삭제됩니다.

Linux의 bash/zsh.

Here-documents 또는 here-strings는 bash5.1 이전 버전에서 zsh삭제된 임시 파일로 구현되었습니다 (1970년대 후반에 here-document가 도입되었을 때 Bourne 쉘의 경우처럼).

그렇다면 다음과 같이 하세요.

exec 3<<< test

파일 설명자 3은 삭제된 임시 파일이 포함된 파일에 연결됩니다 test\n.

다음을 통해 내용을 얻을 수 있습니다.

cat <&3

Linux에서는 파일을 읽거나 쓸 수도 있지만 /dev/fd/3bash 버전 5.0에서는 먼저 파일에 대한 쓰기 권한을 복원해야 합니다(bash는 해당 버전에서 명시적으로 이를 제거했습니다).

$ exec 3<<< test
$ cat <&3
test
$ chmod u+w /dev/fd/3 # only needed in bash 5.0
$ echo foo > /dev/fd/3
$ cat /dev/fd/3
foo

(일부 다른 쉘은 파이프를 사용하거나 /dev/null여기 문서가 비어 있으면 사용할 수 있습니다).

POSIX

POSIX 유틸리티 가 없습니다 mktemp. 그러나 POSIX는mkstemp(template)응용 프로그래밍 인터페이스, 표준 유틸리티는 m4동일한 이름의 m4 함수를 사용하여 이 API를 노출합니다.mkstemp()

mkstemp()함수가 호출될 때 존재하지 않는 것으로 보장되는 임의의 부분이 포함된 파일 이름을 제공합니다. 경쟁 없는 방식으로 권한 0600을 사용하여 파일을 생성합니다.

따라서 다음과 같이 할 수 있습니다.

tmpfile=$(
  echo 'mkstemp(template)' |
    m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit

하지만 종료 시 정리 작업을 처리해야 하지만 파일을 정해진 횟수만큼 쓰고 읽어야 하는 경우 위의 here-doc/here-char처럼 문자열 메서드를 생성한 후 열고 삭제할 수 있습니다. :

tmpfile=$(
  echo 'mkstemp(template)' |
    m4 -D template="${TMPDIR:-/tmp}/baseXXXXXX"
) || exit

# open once for writing, twice for reading:
exec 3> "$tempfile" 4< "$tempfile" 5< "$tempfile"

rm -f -- "$tmpfile"

cmd >&3   # store something in the temp file
exec 3>&- # fd no longer needed

# read the content twice:
cat <&4
cat <&5

한 번의 읽기를 위해 파일을 연 다음 읽기 사이에 되감을 수 있지만 rewind( ) 작업을 수행하는 POSIX 유틸리티가 없으므로 POSIX 스크립트( ( 내장) 및 ( 연산자) lseek()에서는 쉽게 수행할 수 없습니다. 자유롭게 그렇게 할 수 있습니다).zshsysseekksh93<#((...))

답변4

다음은 Hauke ​​​​Laging의 다소 향상된 답변입니다.

#!/bin/bash

tmpfile=$(mktemp)  # Create a temporal file in the default temporal folder of the system

# Lets do some magic for the tmpfile to be removed when this script ends, even if it crashes
exec {FD_W}>"$tmpfile"  # Create file descriptor for writing, using first number available
exec {FD_R}<"$tmpfile"  # Create file descriptor for reading, using first number available
rm "$tmpfile"  # Delete the file, but file descriptors keep available for this script

# Now it is possible to work with the temporal file
echo foo >&$FD_W
echo bar >&$FD_W  # Note that file descriptor always concatenates, not overwrites

cat <&$FD_R

관련 정보